[tracker/wip/carlosg/tracker-3.0-api-breaks: 56/95] libtracker-sparql: Reimplement public API in C



commit f4eb73aacbe4be8d9b2a712576fbe21d01177b45
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sun Aug 18 18:48:01 2019 +0200

    libtracker-sparql: Reimplement public API in C
    
    It is risky and clunky to have API/ABI in control of a transpiler
    like Vala is. Examples are:
    
    - Defining the abstract classes in vala necessarily exports these
      *_construct() functions, which are 100% useless as public API
      since no subclassing of Tracker objects is whatsoever allowed
      outside of Tracker.
    - While on the *_construct() functions topic, adding a constructor
      like tracker_sparql_connetion_new() somehow made valac stop
      exporting one for TrackerSparqlConnection. The warnings are
      somehow eaten when compiling the resulting C code, but hell breaks
      loose when the C compiler assumes an int return value (because
      it can't know better) but the constructor has a pointer-sized
      return value. Since those functions are exported, this change
      sneakily involves an ABI break too.
    - Even though we want some properties to be construct-only, vala
      will automatically export setter functions for those. This adds
      API like tracker_sparql_statement_set_connection() that can only
      break things if ever called.
    - The --abi-stability valac toggle was added too late for Tracker
      to use it. We could use 3.0 as an excuse to turn it on, but that
      doesn't magically fix the other points.
    - Vala doesn't allow us to be explicit wrt the exported functions
      (eg. through extern). We do resort to a .map file, but that's
      prone to errors and hairy to maintain.
    
    We still use vala at places for internal code, but I can't bring
    myself to think it's a good idea to keep vala in charge of our
    public API and ABI.

 src/libtracker-bus/tracker-bus-fd-cursor.vala      |   1 +
 src/libtracker-bus/tracker-bus.vala                |   1 +
 src/libtracker-data/meson.build                    |   1 -
 src/libtracker-direct/tracker-direct-statement.c   |   2 +-
 src/libtracker-direct/tracker-direct.c             |   5 +-
 src/libtracker-fts/meson.build                     |   1 -
 src/libtracker-remote/tracker-json-cursor.vala     |   1 +
 src/libtracker-remote/tracker-remote.vala          |   1 +
 src/libtracker-remote/tracker-xml-cursor.vala      |   1 +
 src/libtracker-sparql-backend/meson.build          |  31 +-
 src/libtracker-sparql/.gitignore                   |   4 -
 .../libtracker-sparql-intermediate-c.vapi          | 115 +++++
 src/libtracker-sparql/meson.build                  |  68 +--
 src/libtracker-sparql/tracker-connection.c         | 478 ++++++++++++++++++++
 src/libtracker-sparql/tracker-connection.h         | 235 ++++++++++
 src/libtracker-sparql/tracker-connection.vala      | 433 ------------------
 src/libtracker-sparql/tracker-cursor.c             | 489 +++++++++++++++++++++
 src/libtracker-sparql/tracker-cursor.h             | 135 ++++++
 src/libtracker-sparql/tracker-cursor.vala          | 294 -------------
 src/libtracker-sparql/tracker-endpoint-dbus.c      |   3 +-
 src/libtracker-sparql/tracker-endpoint.h           |   2 +-
 src/libtracker-sparql/tracker-notifier.c           |   4 +-
 .../{tracker-namespace.vala => tracker-private.h}  |  19 +-
 src/libtracker-sparql/tracker-resource.c           |   2 +-
 .../tracker-sparql-add-include-guards.sh           |  17 -
 src/libtracker-sparql/tracker-sparql.h             |   6 +-
 src/libtracker-sparql/tracker-statement.c          | 357 +++++++++++++++
 src/libtracker-sparql/tracker-statement.h          | 103 +++++
 src/libtracker-sparql/tracker-statement.vala       | 133 ------
 src/libtracker-sparql/tracker-uri.c                |  10 +-
 src/libtracker-sparql/tracker-utils.c              |  80 ++++
 src/libtracker-sparql/tracker-utils.h              |  33 ++
 src/libtracker-sparql/tracker-utils.vala           | 115 -----
 33 files changed, 2075 insertions(+), 1105 deletions(-)
---
diff --git a/src/libtracker-bus/tracker-bus-fd-cursor.vala b/src/libtracker-bus/tracker-bus-fd-cursor.vala
index 751c65349..318d261cb 100644
--- a/src/libtracker-bus/tracker-bus-fd-cursor.vala
+++ b/src/libtracker-bus/tracker-bus-fd-cursor.vala
@@ -30,6 +30,7 @@ class Tracker.Bus.FDCursor : Tracker.Sparql.Cursor {
        internal bool cursor_finished;
 
        public FDCursor (char* buffer, ulong buffer_size, string[] variable_names) {
+               Object ();
                this.buffer = buffer;
                this.buffer_size = buffer_size;
                this.variable_names = variable_names;
diff --git a/src/libtracker-bus/tracker-bus.vala b/src/libtracker-bus/tracker-bus.vala
index b2d1fba82..f6bf84952 100644
--- a/src/libtracker-bus/tracker-bus.vala
+++ b/src/libtracker-bus/tracker-bus.vala
@@ -25,6 +25,7 @@ public class Tracker.Bus.Connection : Tracker.Sparql.Connection {
        private const string ENDPOINT_IFACE = "org.freedesktop.Tracker1.Endpoint";
 
        public Connection (string dbus_name, string object_path, DBusConnection? dbus_connection) throws 
Sparql.Error, IOError, DBusError, GLib.Error {
+               Object ();
                this.dbus_name = dbus_name;
                this.bus = dbus_connection;
                this.object_path = object_path;
diff --git a/src/libtracker-data/meson.build b/src/libtracker-data/meson.build
index 017a9f4d2..a3914819d 100644
--- a/src/libtracker-data/meson.build
+++ b/src/libtracker-data/meson.build
@@ -62,7 +62,6 @@ libtracker_data = library('tracker-data',
     tracker_data_enums[0],
     tracker_data_enums[1],
     tracker_gresources,
-    tracker_sparql_generated_header,
     c_args: tracker_c_args,
     install: true,
     install_dir: tracker_internal_libs_dir,
diff --git a/src/libtracker-direct/tracker-direct-statement.c 
b/src/libtracker-direct/tracker-direct-statement.c
index 0628b1fb5..c2c18b94f 100644
--- a/src/libtracker-direct/tracker-direct-statement.c
+++ b/src/libtracker-direct/tracker-direct-statement.c
@@ -31,7 +31,7 @@ struct _TrackerDirectStatementPrivate
 
 G_DEFINE_TYPE_WITH_PRIVATE (TrackerDirectStatement,
                             tracker_direct_statement,
-                            TRACKER_SPARQL_TYPE_STATEMENT)
+                            TRACKER_TYPE_SPARQL_STATEMENT)
 
 static void
 tracker_direct_statement_finalize (GObject *object)
diff --git a/src/libtracker-direct/tracker-direct.c b/src/libtracker-direct/tracker-direct.c
index e71acd67e..bded34636 100644
--- a/src/libtracker-direct/tracker-direct.c
+++ b/src/libtracker-direct/tracker-direct.c
@@ -22,6 +22,7 @@
 
 #include "tracker-direct.h"
 #include "tracker-direct-statement.h"
+#include "libtracker-sparql/tracker-private.h"
 #include <libtracker-data/tracker-data.h>
 #include <libtracker-data/tracker-sparql.h>
 #include <libtracker-sparql/tracker-notifier-private.h>
@@ -73,7 +74,7 @@ static void tracker_direct_connection_async_initable_iface_init (GAsyncInitableI
 G_DEFINE_QUARK (TrackerDirectNotifier, tracker_direct_notifier)
 
 G_DEFINE_TYPE_WITH_CODE (TrackerDirectConnection, tracker_direct_connection,
-                         TRACKER_SPARQL_TYPE_CONNECTION,
+                         TRACKER_TYPE_SPARQL_CONNECTION,
                          G_ADD_PRIVATE (TrackerDirectConnection)
                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
                                                 tracker_direct_connection_initable_iface_init)
@@ -942,7 +943,7 @@ tracker_direct_connection_class_init (TrackerDirectConnectionClass *klass)
                g_param_spec_enum ("flags",
                                   "Flags",
                                   "Flags",
-                                  TRACKER_SPARQL_TYPE_CONNECTION_FLAGS,
+                                  TRACKER_TYPE_SPARQL_CONNECTION_FLAGS,
                                   TRACKER_SPARQL_CONNECTION_FLAGS_NONE,
                                   G_PARAM_READWRITE |
                                   G_PARAM_CONSTRUCT_ONLY);
diff --git a/src/libtracker-fts/meson.build b/src/libtracker-fts/meson.build
index 5e1eab814..2d340f0a1 100644
--- a/src/libtracker-fts/meson.build
+++ b/src/libtracker-fts/meson.build
@@ -11,7 +11,6 @@ libtracker_fts = static_library('tracker-fts',
     'tracker-fts-config.c',
     'tracker-fts-tokenizer.c',
     libtracker_fts_fts5,
-    tracker_sparql_generated_header,
     dependencies: [tracker_common_dep],
     c_args: tracker_c_args
 )
diff --git a/src/libtracker-remote/tracker-json-cursor.vala b/src/libtracker-remote/tracker-json-cursor.vala
index e46494767..047d47278 100644
--- a/src/libtracker-remote/tracker-json-cursor.vala
+++ b/src/libtracker-remote/tracker-json-cursor.vala
@@ -30,6 +30,7 @@ public class Tracker.Remote.JsonCursor : Tracker.Sparql.Cursor {
        const string XSD_NS = "http://www.w3.org/2001/XMLSchema#";;
 
        public JsonCursor (string document, long length) throws GLib.Error {
+               Object ();
                var parser = new Json.Parser ();
                parser.load_from_data (document, length);
 
diff --git a/src/libtracker-remote/tracker-remote.vala b/src/libtracker-remote/tracker-remote.vala
index d63ed18f1..7d083b12a 100644
--- a/src/libtracker-remote/tracker-remote.vala
+++ b/src/libtracker-remote/tracker-remote.vala
@@ -31,6 +31,7 @@ public class Tracker.Remote.Connection : Tracker.Sparql.Connection {
        const string USER_AGENT = "Tracker/" + PACKAGE_VERSION + " 
(https://gitlab.gnome.org/GNOME/tracker/issues/; tracker-list lists gnome org) Tracker/" + PACKAGE_VERSION;
 
        public Connection (string base_uri) {
+               Object ();
                _base_uri = base_uri;
                _session = new Soup.Session ();
        }
diff --git a/src/libtracker-remote/tracker-xml-cursor.vala b/src/libtracker-remote/tracker-xml-cursor.vala
index ef7349e75..a7a710041 100644
--- a/src/libtracker-remote/tracker-xml-cursor.vala
+++ b/src/libtracker-remote/tracker-xml-cursor.vala
@@ -82,6 +82,7 @@ public class Tracker.Remote.XmlCursor : Tracker.Sparql.Cursor {
        }
 
        public XmlCursor (string document, long length) throws Sparql.Error {
+               Object ();
                Xml.Parser.init ();
                var doc = Xml.Parser.parse_memory (document, (int) length);
 
diff --git a/src/libtracker-sparql-backend/meson.build b/src/libtracker-sparql-backend/meson.build
index c7f49b8fa..81610b6ba 100644
--- a/src/libtracker-sparql-backend/meson.build
+++ b/src/libtracker-sparql-backend/meson.build
@@ -14,7 +14,7 @@ libtracker_sparql = library('tracker-sparql-' + tracker_api_version,
     install_rpath: tracker_internal_libs_dir,
 
     link_args: vflag,
-    link_whole: [libtracker_sparql_intermediate_c, libtracker_sparql_intermediate_vala],
+    link_whole: [libtracker_sparql_intermediate],
 
     dependencies: [tracker_common_dep, tracker_sparql_remote_dep, tracker_sparql_bus_dep, 
tracker_sparql_direct_dep, libtracker_sparql_c_vapi_dep],
 )
@@ -43,40 +43,17 @@ pkg.generate(libtracker_sparql,
     ],
 )
 
-# The introspection generation for libtracker-sparql is awkward because we have
-# both C and Vala code, and we have to generate an introspection repo for each
-# one separately and then combine them together manually.
-#
-# See: <https://bugzilla.gnome.org/show_bug.cgi?id=782091>
-
-tracker_sparql_c_gir = gnome.generate_gir(libtracker_sparql,
+tracker_sparql_gir = gnome.generate_gir(libtracker_sparql,
     sources: libtracker_sparql_c_sources + libtracker_sparql_c_public_headers,
     nsversion: tracker_api_version,
-    namespace: 'Tracker_C',
+    namespace: 'Tracker',
     identifier_prefix: 'Tracker',
     symbol_prefix: 'tracker',
     includes : ['GLib-2.0', 'GObject-2.0', 'Gio-2.0' ],
     link_with: libtracker_sparql,
+    install: true,
     extra_args: [
         '--c-include',
         'libtracker-sparql/tracker-sparql.h',
         '-DTRACKER_COMPILATION',
     ])
-
-tracker_sparql_c_gir = tracker_sparql_c_gir[0]  # Ignore this .typelib
-tracker_sparql_vala_gir = join_paths(meson.current_build_dir(), '..', 'libtracker-sparql', 'Tracker_Vala-' + 
tracker_api_version + '.gir')
-
-tracker_sparql_gir = custom_target('tracker-sparql-gir',
-    command: [g_ir_merge, '--namespace', 'Tracker', '--nsversion', tracker_api_version, '@INPUT@', 
tracker_sparql_vala_gir],
-    input: [tracker_sparql_c_gir],
-    capture: true,
-    output: 'Tracker-@0@.gir'.format(tracker_api_version),
-    install: true,
-    install_dir: gir_dir)
-
-tracker_sparql_typelib = custom_target('tracker-sparql-typelib',
-    command: [g_ir_compiler, '--includedir', meson.current_build_dir(), '--output', '@OUTPUT@', '@INPUT@'],
-    input: tracker_sparql_gir,
-    output: 'Tracker-@0@.typelib'.format(tracker_api_version),
-    install: true,
-    install_dir: typelib_dir)
diff --git a/src/libtracker-sparql/.gitignore b/src/libtracker-sparql/.gitignore
index e16d34f8d..79eb0f739 100644
--- a/src/libtracker-sparql/.gitignore
+++ b/src/libtracker-sparql/.gitignore
@@ -1,12 +1,8 @@
 tracker-namespace.c
-tracker-builder.c
-tracker-connection.c
-tracker-cursor.c
 tracker-backend.c
 tracker-plugin-loader.c
 tracker-query.c
 tracker-sparql-*.deps
 tracker-sparql*.vapi
 tracker-generated*.h
-tracker-utils.c
 *.pc
diff --git a/src/libtracker-sparql/libtracker-sparql-intermediate-c.vapi 
b/src/libtracker-sparql/libtracker-sparql-intermediate-c.vapi
index 79cdf310d..bebd6f82b 100644
--- a/src/libtracker-sparql/libtracker-sparql-intermediate-c.vapi
+++ b/src/libtracker-sparql/libtracker-sparql-intermediate-c.vapi
@@ -18,6 +18,121 @@
  */
 
 namespace Tracker {
+       [CCode (cheader_filename = "libtracker-sparql/tracker-connection.h")]
+       public errordomain Sparql.Error {
+               PARSE,
+               UNKNOWN_CLASS,
+               UNKNOWN_PROPERTY,
+               TYPE,
+               CONSTRAINT,
+               NO_SPACE,
+               INTERNAL,
+               UNSUPPORTED,
+               UNKNOWN_GRAPH
+       }
+
+       [CCode (cheader_filename = "libtracker-sparql/tracker-connection.h")]
+       public enum Sparql.ConnectionFlags {
+               NONE     = 0,
+               READONLY = 1 << 0,
+       }
+
+       [CCode (cheader_filename = "libtracker-sparql/tracker-cursor.h")]
+       public enum Sparql.ValueType {
+               UNBOUND,
+               URI,
+               STRING,
+               INTEGER,
+               DOUBLE,
+               DATETIME,
+               BLANK_NODE,
+               BOOLEAN
+       }
+
+       namespace Sparql {
+               [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h")]
+               public static string escape_string (string literal);
+               [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h")]
+               public static string escape_uri (string uri);
+               [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h")]
+               public static string escape_uri_printf (string format, ...);
+               [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h")]
+               public static string escape_uri_vprintf (string format, va_list args);
+               [CCode (cheader_filename = "libtracker-sparql/tracker-sparql.h")]
+               public static string get_uuid_urn ();
+       }
+
+       [CCode (cheader_filename = "libtracker-sparql/tracker-connection.h")]
+        public abstract class Sparql.Connection : GLib.Object {
+               public extern static new Connection remote_new (string uri_base);
+               public extern static new Connection new (Sparql.ConnectionFlags flags, GLib.File store, 
GLib.File? ontology, GLib.Cancellable? cancellable = null) throws Sparql.Error, GLib.IOError;
+               public extern async static new Connection new_async (Sparql.ConnectionFlags flags, GLib.File 
store, GLib.File? ontology, GLib.Cancellable? cancellable = null) throws Sparql.Error, GLib.IOError;
+               public extern static new Connection bus_new (string service_name, string? object_path, 
GLib.DBusConnection? dbus_connection = null) throws Sparql.Error, GLib.IOError, GLib.DBusError, GLib.Error;
+
+               public abstract Cursor query (string sparql, GLib.Cancellable? cancellable = null) throws 
Sparql.Error, GLib.Error, GLib.IOError, GLib.DBusError;
+               public async abstract Cursor query_async (string sparql, GLib.Cancellable? cancellable = 
null) throws Sparql.Error, GLib.Error, GLib.IOError, GLib.DBusError;
+
+               public virtual void update (string sparql, int priority = GLib.Priority.DEFAULT, 
GLib.Cancellable? cancellable = null) throws Sparql.Error, GLib.Error, GLib.IOError, GLib.DBusError;
+               public async virtual void update_async (string sparql, int priority = GLib.Priority.DEFAULT, 
GLib.Cancellable? cancellable = null) throws Sparql.Error, GLib.Error, GLib.IOError, GLib.DBusError;
+               public async virtual bool update_array_async (string[] sparql, int priority = 
GLib.Priority.DEFAULT, GLib.Cancellable? cancellable = null) throws Sparql.Error, GLib.Error, GLib.IOError, 
GLib.DBusError;
+               public virtual GLib.Variant? update_blank (string sparql, int priority = 
GLib.Priority.DEFAULT, GLib.Cancellable? cancellable = null) throws Sparql.Error, GLib.Error, GLib.IOError, 
GLib.DBusError;
+               public async virtual GLib.Variant? update_blank_async (string sparql, int priority = 
GLib.Priority.DEFAULT, GLib.Cancellable? cancellable = null) throws Sparql.Error, GLib.Error, GLib.IOError, 
GLib.DBusError;
+
+               public virtual NamespaceManager? get_namespace_manager ();
+
+               public extern static void set_domain (string? domain);
+               public extern static string? get_domain ();
+
+               public extern static void set_dbus_connection (GLib.DBusConnection dbus_connection);
+               public extern static GLib.DBusConnection? get_dbus_connection ();
+
+               public virtual Statement? query_statement (string sparql, GLib.Cancellable? cancellable = 
null) throws Sparql.Error;
+
+                public virtual Notifier? create_notifier (NotifierFlags flags);
+                public virtual void close ();
+       }
+
+       [CCode (cheader_filename = "libtracker-sparql/tracker-statement.h")]
+       public abstract class Sparql.Statement : GLib.Object {
+               public string sparql { get; construct set; }
+               public Connection connection { get; construct set; }
+
+               public abstract void bind_int (string name, int64 value);
+               public abstract void bind_boolean (string name, bool value);
+               public abstract void bind_string (string name, string value);
+               public abstract void bind_double (string name, double value);
+
+               public abstract Cursor execute (GLib.Cancellable? cancellable) throws Sparql.Error, 
GLib.Error, GLib.IOError, GLib.DBusError;
+               public async abstract Cursor execute_async (GLib.Cancellable? cancellable) throws 
Sparql.Error, GLib.Error, GLib.IOError, GLib.DBusError;
+       }
+
+       [CCode (cheader_filename = "libtracker-sparql/tracker-cursor.h")]
+       public abstract class Sparql.Cursor : GLib.Object {
+               public Connection connection {
+                       get;
+                       set;
+               }
+
+               public abstract int n_columns {
+                       get;
+               }
+
+               public abstract Sparql.ValueType get_value_type (int column);
+
+               public abstract unowned string? get_variable_name (int column);
+               public abstract unowned string? get_string (int column, out long length = null);
+
+               public abstract bool next (GLib.Cancellable? cancellable = null) throws GLib.Error;
+               public async abstract bool next_async (GLib.Cancellable? cancellable = null) throws 
GLib.Error;
+               public abstract void rewind ();
+               public virtual void close ();
+
+               public virtual int64 get_integer (int column);
+               public virtual double get_double (int column);
+               public virtual bool get_boolean (int column);
+               public virtual bool is_bound (int column);
+       }
+
        [CCode (cheader_filename = "libtracker-sparql/tracker-namespace-manager.h")]
        public class NamespaceManager : GLib.Object {
                public NamespaceManager ();
diff --git a/src/libtracker-sparql/meson.build b/src/libtracker-sparql/meson.build
index 51d89d196..3fb684f2f 100644
--- a/src/libtracker-sparql/meson.build
+++ b/src/libtracker-sparql/meson.build
@@ -1,87 +1,51 @@
-enums_c = gnome.mkenums('tracker-sparql-enum-types',
-    sources: 'tracker-notifier.h',
+enum_types = gnome.mkenums('tracker-sparql-enum-types',
+    sources: ['tracker-notifier.h', 'tracker-connection.h'],
     c_template: 'tracker-sparql-enum-types.c.template',
-)
-enums_h = gnome.mkenums('tracker-sparql-enum-types',
-    sources: 'tracker-notifier.h',
     h_template: 'tracker-sparql-enum-types.h.template',
+    install_dir: join_paths(get_option('prefix'), get_option('includedir'), 
'tracker-@0@'.format(tracker_api_version), 'libtracker-sparql'),
+    install_header: true,
 )
 
-# First build the Vala parts ...
 libtracker_sparql_c_vapi = files('libtracker-sparql-intermediate-c.vapi')
 libtracker_sparql_c_vapi_dep = meson.get_compiler('vala').find_library('libtracker-sparql-intermediate-c', 
dirs: meson.current_source_dir())
 
-libtracker_sparql_intermediate_vala = static_library('tracker-sparql-intermediate-vala',
-    'tracker-namespace.vala',
-    'tracker-connection.vala',
-    'tracker-cursor.vala',
-    'tracker-statement.vala',
-    'tracker-utils.vala',
-    vala_header: 'tracker-generated-no-checks.h',
-    c_args: tracker_c_args,
-    vala_gir: 'Tracker_Vala-' + tracker_api_version + '.gir',
-    vala_args: [
-        '--debug',
-        '--includedir', 'libtracker-sparql',
-        '--pkg', 'gio-2.0', '--pkg', 'posix',
-        # FIXME: Meson has code to add --target-glib automatically, but it
-        # doesn't seem to work here.
-        '--target-glib', glib_required,
-        libtracker_sparql_c_vapi
-    ],
-    dependencies: [tracker_common_dep],
-    include_directories: [commoninc, configinc, srcinc],
-)
-
-# We must postprocess the generated Vala header to have only-include-once guards
-tracker_sparql_generated_header = custom_target('tracker-sparql-generated-header',
-    # FIXME: can't list tracker-generated-no-checks as an input, even though it
-    # is, because you'll see this:
-    #
-    #     ninja: error:
-    #     '../src/libtracker-sparql/tracker-generated-no-checks.h', needed by
-    #     'src/libtracker-sparql/tracker-generated.h', missing and no known
-    #     rule to make it
-    #
-    output: 'tracker-generated.h',
-    command: [join_paths(meson.current_source_dir(), 'tracker-sparql-add-include-guards.sh'), 
join_paths(meson.current_build_dir(), 'tracker-generated-no-checks.h'), '@OUTPUT@'],
-    depends: libtracker_sparql_intermediate_vala,
-    install: true,
-    install_dir: join_paths(get_option('prefix'), get_option('includedir'), 
'tracker-@0@'.format(tracker_api_version), 'libtracker-sparql'))
-
-# Now build the C parts ...
-
 libtracker_sparql_c_sources = files(
+    'tracker-connection.c',
+    'tracker-cursor.c',
     'tracker-endpoint.c',
     'tracker-endpoint-dbus.c',
     'tracker-namespace-manager.c',
     'tracker-notifier.c',
     'tracker-resource.c',
+    'tracker-statement.c',
     'tracker-uri.c',
+    'tracker-utils.c',
     'tracker-version.c',
 )
 
 libtracker_sparql_c_public_headers = files(
+    'tracker-connection.h',
+    'tracker-cursor.h',
     'tracker-endpoint.h',
     'tracker-endpoint-dbus.h',
     'tracker-namespace-manager.h',
     'tracker-notifier.h',
     'tracker-resource.h',
+    'tracker-statement.h',
+    'tracker-utils.h',
     'tracker-version.h',
 )
 
-libtracker_sparql_intermediate_c = static_library('tracker-sparql-intermediate-c',
-    enums_c, enums_h, tracker_sparql_generated_header[0],
+libtracker_sparql_intermediate = static_library('tracker-sparql-intermediate',
+    enum_types,
     libtracker_sparql_c_sources,
     dependencies: [tracker_common_dep, json_glib],
-    link_with: libtracker_sparql_intermediate_vala,
 )
 
 sparqlinc = [include_directories('.'), meson.current_build_dir()]
 
 tracker_sparql_intermediate_dep = declare_dependency(
-    link_with: [libtracker_sparql_intermediate_c, libtracker_sparql_intermediate_vala],
-    sources: tracker_sparql_generated_header,
+    link_with: [libtracker_sparql_intermediate],
     include_directories: [srcinc, include_directories('.')],
     dependencies: [ libtracker_sparql_c_vapi_dep ],
 )
@@ -99,9 +63,7 @@ tracker_sparql_vapi = custom_target('tracker-sparql-' + tracker_api_version + '.
     command: [
         'sed', '-e', 's#libtracker-sparql/.*[.]h#libtracker-sparql/tracker-sparql.h#',
         libtracker_sparql_c_vapi,
-        join_paths(meson.current_build_dir(), 'tracker-sparql-intermediate-vala.vapi')
     ],
-    depends: libtracker_sparql_intermediate_vala,
     capture: true,
     install: true,
     install_dir: vapi_dir)
diff --git a/src/libtracker-sparql/tracker-connection.c b/src/libtracker-sparql/tracker-connection.c
new file mode 100644
index 000000000..be578f4de
--- /dev/null
+++ b/src/libtracker-sparql/tracker-connection.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2010, Nokia <ivan frade nokia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+#include "config.h"
+
+#include "tracker-connection.h"
+
+G_DEFINE_ABSTRACT_TYPE (TrackerSparqlConnection, tracker_sparql_connection,
+                        G_TYPE_OBJECT)
+
+G_DEFINE_QUARK (tracker-sparql-error-quark, tracker_sparql_error)
+
+static void
+tracker_sparql_connection_init (TrackerSparqlConnection *connection)
+{
+}
+
+static void
+tracker_sparql_connection_class_init (TrackerSparqlConnectionClass *klass)
+{
+}
+
+/**
+ * tracker_sparql_connection_query:
+ * @connection: a #TrackerSparqlConnection
+ * @sparql: string containing the SPARQL query
+ * @cancellable: a #GCancellable used to cancel the operation
+ * @error: #GError for error reporting.
+ *
+ * Executes a SPARQL query on. The API call is completely synchronous, so
+ * it may block.
+ *
+ * The @sparql query should be built with #TrackerResource, or
+ * its parts correctly escaped using tracker_sparql_escape_string(),
+ * otherwise SPARQL injection is possible.
+ *
+ * Returns: (transfer full): a #TrackerSparqlCursor if results were found.
+ * On error, #NULL is returned and the @error is set accordingly.
+ * Call g_object_unref() on the returned cursor when no longer needed.
+ */
+TrackerSparqlCursor *
+tracker_sparql_connection_query (TrackerSparqlConnection  *connection,
+                                 const gchar              *sparql,
+                                 GCancellable             *cancellable,
+                                 GError                  **error)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection), NULL);
+       g_return_val_if_fail (sparql != NULL, NULL);
+       g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL);
+       g_return_val_if_fail (!error || !*error, NULL);
+
+       return TRACKER_SPARQL_CONNECTION_GET_CLASS (connection)->query (connection,
+                                                                       sparql,
+                                                                       cancellable,
+                                                                       error);
+}
+
+/**
+ * tracker_sparql_connection_query_async:
+ * @connection: a #TrackerSparqlConnection
+ * @sparql: string containing the SPARQL query
+ * @cancellable: a #GCancellable used to cancel the operation
+ * @callback: user-defined #GAsyncReadyCallback to be called when
+ *            asynchronous operation is finished.
+ * @user_data: user-defined data to be passed to @callback
+ *
+ * Executes asynchronously a SPARQL query.
+ */
+void
+tracker_sparql_connection_query_async (TrackerSparqlConnection *connection,
+                                       const gchar             *sparql,
+                                       GCancellable            *cancellable,
+                                       GAsyncReadyCallback      callback,
+                                       gpointer                 user_data)
+{
+       g_return_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection));
+       g_return_if_fail (sparql != NULL);
+       g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+       TRACKER_SPARQL_CONNECTION_GET_CLASS (connection)->query_async (connection,
+                                                                      sparql,
+                                                                      cancellable,
+                                                                      callback,
+                                                                      user_data);
+}
+
+/**
+ * tracker_sparql_connection_query_finish:
+ * @connection: a #TrackerSparqlConnection
+ * @res: a #GAsyncResult with the result of the operation
+ * @error: #GError for error reporting.
+ *
+ * Finishes the asynchronous SPARQL query operation.
+ *
+ * Returns: (transfer full): a #TrackerSparqlCursor if results were found.
+ * On error, #NULL is returned and the @error is set accordingly.
+ * Call g_object_unref() on the returned cursor when no longer needed.
+ */
+TrackerSparqlCursor *
+tracker_sparql_connection_query_finish (TrackerSparqlConnection  *connection,
+                                        GAsyncResult             *res,
+                                        GError                  **error)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection), NULL);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
+       g_return_val_if_fail (!error || !*error, NULL);
+
+       return TRACKER_SPARQL_CONNECTION_GET_CLASS (connection)->query_finish (connection,
+                                                                              res,
+                                                                              error);
+}
+
+/**
+ * tracker_sparql_connection_update:
+ * @connection: a #TrackerSparqlConnection
+ * @sparql: string containing the SPARQL update query
+ * @priority: the priority for the operation
+ * @cancellable: a #GCancellable used to cancel the operation
+ * @error: #GError for error reporting.
+ *
+ * Executes a SPARQL update. The API call is completely
+ * synchronous, so it may block.
+ *
+ * The @sparql query should be built with #TrackerResource, or
+ * its parts correctly escaped using tracker_sparql_escape_string(),
+ * otherwise SPARQL injection is possible.
+ */
+void
+tracker_sparql_connection_update (TrackerSparqlConnection  *connection,
+                                  const gchar              *sparql,
+                                  gint                      priority,
+                                  GCancellable             *cancellable,
+                                  GError                  **error)
+{
+       g_return_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection));
+       g_return_if_fail (sparql != NULL);
+       g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+       g_return_if_fail (!error || !*error);
+
+       return TRACKER_SPARQL_CONNECTION_GET_CLASS (connection)->update (connection,
+                                                                        sparql,
+                                                                        priority,
+                                                                        cancellable,
+                                                                        error);
+}
+
+/**
+ * tracker_sparql_connection_update_async:
+ * @connection: a #TrackerSparqlConnection
+ * @sparql: string containing the SPARQL update query
+ * @priority: the priority for the asynchronous operation
+ * @cancellable: a #GCancellable used to cancel the operation
+ * @callback: user-defined #GAsyncReadyCallback to be called when
+ *            asynchronous operation is finished.
+ * @user_data: user-defined data to be passed to @callback
+ *
+ * Executes asynchronously a SPARQL update.
+ */
+void
+tracker_sparql_connection_update_async (TrackerSparqlConnection *connection,
+                                        const gchar             *sparql,
+                                        gint                     priority,
+                                        GCancellable            *cancellable,
+                                        GAsyncReadyCallback      callback,
+                                        gpointer                 user_data)
+{
+       g_return_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection));
+       g_return_if_fail (sparql != NULL);
+       g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+       TRACKER_SPARQL_CONNECTION_GET_CLASS (connection)->update_async (connection,
+                                                                       sparql,
+                                                                       priority,
+                                                                       cancellable,
+                                                                       callback,
+                                                                       user_data);
+}
+
+/**
+ * tracker_sparql_connection_update_finish:
+ * @connection: a #TrackerSparqlConnection
+ * @res: a #GAsyncResult with the result of the operation
+ * @error: #GError for error reporting.
+ *
+ * Finishes the asynchronous SPARQL update operation.
+ */
+void
+tracker_sparql_connection_update_finish (TrackerSparqlConnection  *connection,
+                                         GAsyncResult             *res,
+                                         GError                  **error)
+{
+       g_return_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection));
+       g_return_if_fail (G_IS_ASYNC_RESULT (res));
+       g_return_if_fail (!error || !*error);
+
+       return TRACKER_SPARQL_CONNECTION_GET_CLASS (connection)->update_finish (connection,
+                                                                               res,
+                                                                               error);
+}
+
+/**
+ * tracker_sparql_connection_update_array_async:
+ * @connection: a #TrackerSparqlConnection
+ * @sparql: an array of strings containing the SPARQL update queries
+ * @sparql_length: the amount of strings you pass as @sparql
+ * @priority: the priority for the asynchronous operation
+ * @cancellable: a #GCancellable used to cancel the operation
+ * @callback: user-defined #GAsyncReadyCallback to be called when
+ *            asynchronous operation is finished.
+ * @user_data: user-defined data to be passed to @callback
+ *
+ * Executes asynchronously an array of SPARQL updates. Each update in the
+ * array is its own transaction. This means that update n+1 is not halted
+ * due to an error in update n.
+ */
+void
+tracker_sparql_connection_update_array_async (TrackerSparqlConnection  *connection,
+                                              gchar                   **sparql,
+                                              gint                      sparql_length,
+                                              gint                      priority,
+                                              GCancellable             *cancellable,
+                                              GAsyncReadyCallback       callback,
+                                              gpointer                  user_data)
+{
+       g_return_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection));
+       g_return_if_fail (sparql != NULL);
+       g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+       TRACKER_SPARQL_CONNECTION_GET_CLASS (connection)->update_array_async (connection,
+                                                                             sparql,
+                                                                             sparql_length,
+                                                                             priority,
+                                                                             cancellable,
+                                                                             callback,
+                                                                             user_data);
+}
+
+/**
+ * tracker_sparql_connection_update_array_finish:
+ * @connection: a #TrackerSparqlConnection
+ * @res: a #GAsyncResult with the result of the operation
+ * @error: #GError for error reporting.
+ *
+ * Finishes the asynchronous SPARQL update_array operation.
+ *
+ * <example>
+ * <programlisting>
+ * static void
+ * async_update_array_callback (GObject      *source_object,
+ *                              GAsyncResult *result,
+ *                              gpointer      user_data)
+ * {
+ *     GError *error = NULL;
+ *     GPtrArray *errors;
+ *     guint i;
+ *
+ *     errors = tracker_sparql_connection_update_array_finish (connection, result, &error);
+ *     g_assert_no_error (error);
+ *
+ *     for (i = 0; i < errors->len; i++) {
+ *         const GError *e = g_ptr_array_index (errors, i);
+ *
+ *         ...
+ *     }
+ *
+ *     g_ptr_array_unref (errors);
+ * }
+ * </programlisting>
+ * </example>
+ *
+ * Returns: a #GPtrArray of size @sparql_length with elements that are
+ * either NULL or a GError instance. The returned array should be freed with
+ * g_ptr_array_unref when no longer used, not with g_ptr_array_free. When
+ * you use errors of the array, you must g_error_copy them. Errors inside of
+ * the array must be considered as const data and not freed. The index of
+ * the error corresponds to the index of the update query in the array that
+ * you passed to tracker_sparql_connection_update_array_async.
+ */
+gboolean
+tracker_sparql_connection_update_array_finish (TrackerSparqlConnection  *connection,
+                                               GAsyncResult             *res,
+                                               GError                  **error)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
+       g_return_val_if_fail (!error || !*error, FALSE);
+
+       return TRACKER_SPARQL_CONNECTION_GET_CLASS (connection)->update_array_finish (connection,
+                                                                                     res,
+                                                                                     error);
+
+}
+
+/**
+ * tracker_sparql_connection_update_blank:
+ * @connection: a #TrackerSparqlConnection
+ * @sparql: string containing the SPARQL update query
+ * @priority: the priority for the operation
+ * @cancellable: a #GCancellable used to cancel the operation
+ * @error: #GError for error reporting.
+ *
+ * Executes a SPARQL update and returns the URNs of the generated nodes,
+ * if any. The API call is completely synchronous, so it may block.
+ *
+ * The @sparql query should be built with #TrackerResource, or
+ * its parts correctly escaped using tracker_sparql_escape_string(),
+ * otherwise SPARQL injection is possible.
+ *
+ * Returns: a #GVariant with the generated URNs, which should be freed with
+ * g_variant_unref() when no longer used.
+ */
+GVariant *
+tracker_sparql_connection_update_blank (TrackerSparqlConnection  *connection,
+                                        const gchar              *sparql,
+                                        gint                      priority,
+                                        GCancellable             *cancellable,
+                                        GError                  **error)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection), NULL);
+       g_return_val_if_fail (sparql != NULL, NULL);
+       g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL);
+       g_return_val_if_fail (!error || !*error, NULL);
+
+       return TRACKER_SPARQL_CONNECTION_GET_CLASS (connection)->update_blank (connection,
+                                                                              sparql,
+                                                                              priority,
+                                                                              cancellable,
+                                                                              error);
+}
+
+/**
+ * tracker_sparql_connection_update_blank_async:
+ * @connection: a #TrackerSparqlConnection
+ * @sparql: string containing the SPARQL update query
+ * @priority: the priority for the asynchronous operation
+ * @cancellable: a #GCancellable used to cancel the operation
+ * @callback: user-defined #GAsyncReadyCallback to be called when
+ *            asynchronous operation is finished.
+ * @user_data: user-defined data to be passed to @callback
+ *
+ * Executes asynchronously a SPARQL update.
+ */
+void
+tracker_sparql_connection_update_blank_async (TrackerSparqlConnection *connection,
+                                              const gchar             *sparql,
+                                              gint                     priority,
+                                              GCancellable            *cancellable,
+                                              GAsyncReadyCallback      callback,
+                                              gpointer                 user_data)
+{
+       g_return_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection));
+       g_return_if_fail (sparql != NULL);
+       g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+       TRACKER_SPARQL_CONNECTION_GET_CLASS (connection)->update_blank_async (connection,
+                                                                             sparql,
+                                                                             priority,
+                                                                             cancellable,
+                                                                             callback,
+                                                                             user_data);
+}
+
+/**
+ * tracker_sparql_connection_update_blank_finish:
+ * @connection: a #TrackerSparqlConnection
+ * @res: a #GAsyncResult with the result of the operation
+ * @error: #GError for error reporting.
+ *
+ * Finishes the asynchronous SPARQL update operation, and returns
+ * the URNs of the generated nodes, if any.
+ *
+ * Returns: a #GVariant with the generated URNs, which should be freed with
+ * g_variant_unref() when no longer used.
+ */
+GVariant *
+tracker_sparql_connection_update_blank_finish (TrackerSparqlConnection  *connection,
+                                               GAsyncResult             *res,
+                                               GError                  **error)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection), NULL);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
+       g_return_val_if_fail (!error || !*error, NULL);
+
+       return TRACKER_SPARQL_CONNECTION_GET_CLASS (connection)->update_blank_finish (connection,
+                                                                               res,
+                                                                               error);
+}
+
+/**
+ * tracker_sparql_connection_get_namespace_manager:
+ * @connection: a #TrackerSparqlConnection
+ *
+ * Retrieves a #TrackerNamespaceManager that contains all
+ * prefixes in the ontology of @connection.
+ *
+ * Returns: (transfer none): a #TrackerNamespaceManager for this
+ * connection. This object is owned by @connection and must not be freed.
+ */
+TrackerNamespaceManager *
+tracker_sparql_connection_get_namespace_manager (TrackerSparqlConnection *connection)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection), NULL);
+
+       return TRACKER_SPARQL_CONNECTION_GET_CLASS (connection)->get_namespace_manager (connection);
+}
+
+/**
+ * tracker_sparql_connection_query_statement:
+ * @connection: a #TrackerSparqlConnection
+ * @sparql: the SPARQL query
+ * @cancellable: a #GCancellable used to cancel the operation, or %NULL
+ * @error: a #TrackerSparqlError or %NULL if no error occured
+ *
+ * Prepares the given @sparql as a #TrackerSparqlStatement.
+ *
+ * Returns: (transfer full) (nullable): a prepared statement
+ */
+TrackerSparqlStatement *
+tracker_sparql_connection_query_statement (TrackerSparqlConnection  *connection,
+                                           const gchar              *sparql,
+                                           GCancellable             *cancellable,
+                                           GError                  **error)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection), NULL);
+       g_return_val_if_fail (sparql != NULL, NULL);
+       g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL);
+       g_return_val_if_fail (!error || !*error, NULL);
+
+       return TRACKER_SPARQL_CONNECTION_GET_CLASS (connection)->query_statement (connection,
+                                                                                 sparql,
+                                                                                 cancellable,
+                                                                                 error);
+}
+
+TrackerNotifier *
+tracker_sparql_connection_create_notifier (TrackerSparqlConnection *connection,
+                                           TrackerNotifierFlags     flags)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection), NULL);
+
+       return TRACKER_SPARQL_CONNECTION_GET_CLASS (connection)->create_notifier (connection, flags);
+}
+
+/**
+ * tracker_sparql_connection_close:
+ * @self: a #TrackerSparqlConnection
+ *
+ * Closes a SPARQL connection. No other API calls than g_object_unref()
+ * should happen after this call.
+ *
+ * This call is blocking. All pending updates will be flushed, and the
+ * store databases will be closed orderly. All ongoing SELECT queries
+ * will be cancelled.
+ *
+ * Since: 3.0
+ */
+void
+tracker_sparql_connection_close (TrackerSparqlConnection *connection)
+{
+       g_return_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection));
+
+       TRACKER_SPARQL_CONNECTION_GET_CLASS (connection)->close (connection);
+}
diff --git a/src/libtracker-sparql/tracker-connection.h b/src/libtracker-sparql/tracker-connection.h
new file mode 100644
index 000000000..6540d9c57
--- /dev/null
+++ b/src/libtracker-sparql/tracker-connection.h
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2010, Nokia <ivan frade nokia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+#ifndef __TRACKER_SPARQL_CONNECTION_H__
+#define __TRACKER_SPARQL_CONNECTION_H__
+
+#if !defined (__LIBTRACKER_SPARQL_INSIDE__) && !defined (TRACKER_COMPILATION)
+#error "only <libtracker-sparql/tracker-sparql.h> must be included directly."
+#endif
+
+#include "tracker-notifier.h"
+
+#include <gio/gio.h>
+
+typedef enum {
+       TRACKER_SPARQL_CONNECTION_FLAGS_NONE     = 0,
+       TRACKER_SPARQL_CONNECTION_FLAGS_READONLY = 1 << 0,
+} TrackerSparqlConnectionFlags;
+
+/**
+ * TrackerSparqlConnection:
+ *
+ * The <structname>TrackerSparqlConnection</structname> object represents a
+ * SPARQL connection.
+ */
+#define TRACKER_TYPE_SPARQL_CONNECTION tracker_sparql_connection_get_type ()
+#define TRACKER_SPARQL_TYPE_CONNECTION TRACKER_TYPE_SPARQL_CONNECTION
+G_DECLARE_DERIVABLE_TYPE (TrackerSparqlConnection,
+                          tracker_sparql_connection,
+                          TRACKER, SPARQL_CONNECTION,
+                          GObject)
+
+#include "tracker-cursor.h"
+#include "tracker-statement.h"
+#include "tracker-namespace-manager.h"
+
+/**
+ * TrackerSparqlError:
+ * @TRACKER_SPARQL_ERROR_PARSE: Error parsing the SPARQL string.
+ * @TRACKER_SPARQL_ERROR_UNKNOWN_CLASS: Unknown class.
+ * @TRACKER_SPARQL_ERROR_UNKNOWN_PROPERTY: Unknown property.
+ * @TRACKER_SPARQL_ERROR_TYPE: Wrong type.
+ * @TRACKER_SPARQL_ERROR_CONSTRAINT: Subject is not in the domain of a property or
+ *                             trying to set multiple values for a single valued
+ *                             property.
+ * @TRACKER_SPARQL_ERROR_NO_SPACE: There was no disk space available to perform the request.
+ * @TRACKER_SPARQL_ERROR_INTERNAL: Internal error.
+ * @TRACKER_SPARQL_ERROR_UNSUPPORTED: Unsupported feature or method.
+ * @TRACKER_SPARQL_ERROR_UNKNOWN_GRAPH: Unknown graph.
+ *
+ * Error domain for Tracker Sparql. Errors in this domain will be from the
+ * #TrackerSparqlError enumeration. See #GError for more information on error
+ * domains.
+ */
+typedef enum {
+       TRACKER_SPARQL_ERROR_PARSE,
+       TRACKER_SPARQL_ERROR_UNKNOWN_CLASS,
+       TRACKER_SPARQL_ERROR_UNKNOWN_PROPERTY,
+       TRACKER_SPARQL_ERROR_TYPE,
+       TRACKER_SPARQL_ERROR_CONSTRAINT,
+       TRACKER_SPARQL_ERROR_NO_SPACE,
+       TRACKER_SPARQL_ERROR_INTERNAL,
+       TRACKER_SPARQL_ERROR_UNSUPPORTED,
+       TRACKER_SPARQL_ERROR_UNKNOWN_GRAPH
+} TrackerSparqlError;
+
+#define TRACKER_SPARQL_ERROR tracker_sparql_error_quark ()
+
+struct _TrackerSparqlConnectionClass
+{
+       GObjectClass parent_class;
+
+        TrackerSparqlCursor * (* query) (TrackerSparqlConnection  *connection,
+                                         const gchar              *sparql,
+                                         GCancellable             *cancellable,
+                                         GError                  **error);
+       void (* query_async) (TrackerSparqlConnection *connection,
+                             const gchar             *sparql,
+                             GCancellable            *cancellable,
+                             GAsyncReadyCallback      callback,
+                             gpointer                 user_data);
+        TrackerSparqlCursor * (* query_finish) (TrackerSparqlConnection  *connection,
+                                                GAsyncResult             *res,
+                                                GError                  **error);
+        void (* update) (TrackerSparqlConnection  *connection,
+                         const gchar              *sparql,
+                         gint                      priority,
+                         GCancellable             *cancellable,
+                         GError                  **error);
+        void (* update_async) (TrackerSparqlConnection *connection,
+                               const gchar             *sparql,
+                               gint                     priority,
+                               GCancellable            *cancellable,
+                               GAsyncReadyCallback      callback,
+                               gpointer                 user_data);
+        void (* update_finish) (TrackerSparqlConnection  *connection,
+                                GAsyncResult             *res,
+                                GError                  **error);
+        void (* update_array_async) (TrackerSparqlConnection  *connection,
+                                     gchar                   **sparql,
+                                     gint                      sparql_length,
+                                     gint                      priority,
+                                     GCancellable             *cancellable,
+                                     GAsyncReadyCallback       callback,
+                                     gpointer                  user_data);
+        gboolean (* update_array_finish) (TrackerSparqlConnection  *connection,
+                                          GAsyncResult             *res,
+                                          GError                  **error);
+        GVariant* (* update_blank) (TrackerSparqlConnection  *connection,
+                                    const gchar              *sparql,
+                                    gint                      priority,
+                                    GCancellable             *cancellable,
+                                    GError                  **error);
+        void (* update_blank_async) (TrackerSparqlConnection *connection,
+                                     const gchar             *sparql,
+                                     gint                     priority,
+                                     GCancellable            *cancellable,
+                                     GAsyncReadyCallback      callback,
+                                     gpointer                 user_data);
+        GVariant* (* update_blank_finish) (TrackerSparqlConnection  *connection,
+                                           GAsyncResult             *res,
+                                           GError                  **error);
+        TrackerNamespaceManager * (* get_namespace_manager) (TrackerSparqlConnection *connection);
+        TrackerSparqlStatement * (* query_statement) (TrackerSparqlConnection  *connection,
+                                                      const gchar              *sparql,
+                                                      GCancellable             *cancellable,
+                                                      GError                  **error);
+       TrackerNotifier * (* create_notifier) (TrackerSparqlConnection *connection,
+                                              TrackerNotifierFlags     flags);
+
+       void (* close) (TrackerSparqlConnection *connection);
+};
+
+GQuark tracker_sparql_error_quark (void);
+
+TrackerSparqlConnection * tracker_sparql_connection_new (TrackerSparqlConnectionFlags   flags,
+                                                         GFile                         *store,
+                                                         GFile                         *ontology,
+                                                         GCancellable                  *cancellable,
+                                                         GError                       **error);
+void tracker_sparql_connection_new_async (TrackerSparqlConnectionFlags   flags,
+                                          GFile                         *store,
+                                          GFile                         *ontology,
+                                          GCancellable                  *cancellable,
+                                          GAsyncReadyCallback            callback,
+                                          gpointer                       user_data);
+TrackerSparqlConnection * tracker_sparql_connection_new_finish (GAsyncResult  *result,
+                                                                GError       **error);
+
+TrackerSparqlConnection * tracker_sparql_connection_bus_new (const gchar      *service_name,
+                                                             const gchar      *object_path,
+                                                             GDBusConnection  *dbus_connection,
+                                                             GError          **error);
+TrackerSparqlConnection * tracker_sparql_connection_remote_new (const gchar *uri_base);
+
+TrackerSparqlCursor * tracker_sparql_connection_query (TrackerSparqlConnection  *connection,
+                                                       const gchar              *sparql,
+                                                       GCancellable             *cancellable,
+                                                       GError                  **error);
+
+void tracker_sparql_connection_query_async (TrackerSparqlConnection *connection,
+                                            const gchar             *sparql,
+                                            GCancellable            *cancellable,
+                                            GAsyncReadyCallback      callback,
+                                            gpointer                 user_data);
+TrackerSparqlCursor * tracker_sparql_connection_query_finish (TrackerSparqlConnection  *connection,
+                                                              GAsyncResult             *res,
+                                                              GError                  **error);
+
+void tracker_sparql_connection_update (TrackerSparqlConnection  *connection,
+                                       const gchar              *sparql,
+                                       gint                      priority,
+                                       GCancellable             *cancellable,
+                                       GError                  **error);
+void tracker_sparql_connection_update_async (TrackerSparqlConnection *connection,
+                                             const gchar             *sparql,
+                                             gint                     priority,
+                                             GCancellable            *cancellable,
+                                             GAsyncReadyCallback      callback,
+                                             gpointer                 user_data);
+void tracker_sparql_connection_update_finish (TrackerSparqlConnection  *connection,
+                                              GAsyncResult             *res,
+                                              GError                  **error);
+void tracker_sparql_connection_update_array_async (TrackerSparqlConnection  *connection,
+                                                   gchar                   **sparql,
+                                                   gint                      sparql_length,
+                                                   gint                      priority,
+                                                   GCancellable             *cancellable,
+                                                   GAsyncReadyCallback       callback,
+                                                   gpointer                  user_data);
+gboolean tracker_sparql_connection_update_array_finish (TrackerSparqlConnection  *connection,
+                                                        GAsyncResult             *res,
+                                                        GError                  **error);
+GVariant * tracker_sparql_connection_update_blank (TrackerSparqlConnection  *connection,
+                                                   const gchar              *sparql,
+                                                   gint                      priority,
+                                                   GCancellable             *cancellable,
+                                                   GError                  **error);
+void tracker_sparql_connection_update_blank_async (TrackerSparqlConnection *connection,
+                                                   const gchar             *sparql,
+                                                   gint                     priority,
+                                                   GCancellable            *cancellable,
+                                                   GAsyncReadyCallback      callback,
+                                                   gpointer                 user_data);
+GVariant * tracker_sparql_connection_update_blank_finish (TrackerSparqlConnection  *connection,
+                                                          GAsyncResult             *res,
+                                                          GError                  **error);
+
+TrackerNamespaceManager * tracker_sparql_connection_get_namespace_manager (TrackerSparqlConnection 
*connection);
+
+TrackerSparqlStatement * tracker_sparql_connection_query_statement (TrackerSparqlConnection  *connection,
+                                                                    const gchar              *sparql,
+                                                                    GCancellable             *cancellable,
+                                                                    GError                  **error);
+TrackerNotifier * tracker_sparql_connection_create_notifier (TrackerSparqlConnection *connection,
+                                                             TrackerNotifierFlags     flags);
+
+void tracker_sparql_connection_close (TrackerSparqlConnection *connection);
+
+#endif /* __TRACKER_SPARQL_CONNECTION_H__ */
diff --git a/src/libtracker-sparql/tracker-cursor.c b/src/libtracker-sparql/tracker-cursor.c
new file mode 100644
index 000000000..2bc8efa73
--- /dev/null
+++ b/src/libtracker-sparql/tracker-cursor.c
@@ -0,0 +1,489 @@
+/*
+ * Copyright (C) 2010, Nokia <ivan frade nokia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+/**
+ * SECTION: tracker-sparql-cursor
+ * @short_description: Iteration of the query results
+ * @title: TrackerSparqlCursor
+ * @stability: Stable
+ * @include: tracker-sparql.h
+ *
+ * <para>
+ * #TrackerSparqlCursor is an object which provides methods to iterate the
+ * results of a query to the Tracker Store.
+ * </para>
+ */
+#include "config.h"
+
+#include "tracker-cursor.h"
+
+enum {
+       PROP_0,
+       PROP_CONNECTION,
+       PROP_N_COLUMNS,
+       N_PROPS
+};
+
+static GParamSpec *props[N_PROPS];
+
+typedef struct {
+       TrackerSparqlConnection *connection;
+       gint n_columns;
+} TrackerSparqlCursorPrivate;
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (TrackerSparqlCursor, tracker_sparql_cursor,
+                                     G_TYPE_OBJECT)
+
+static void
+tracker_sparql_cursor_init (TrackerSparqlCursor *cursor)
+{
+}
+
+static gint64
+tracker_sparql_cursor_real_get_integer (TrackerSparqlCursor *cursor,
+                                        gint                 column)
+{
+       if (tracker_sparql_cursor_get_value_type (cursor, column) == TRACKER_SPARQL_VALUE_TYPE_INTEGER) {
+               const gchar *text;
+
+               text = tracker_sparql_cursor_get_string (cursor, column, NULL);
+               return g_ascii_strtoll (text, NULL, 10);
+       }
+
+       return 0;
+}
+
+static gdouble
+tracker_sparql_cursor_real_get_double (TrackerSparqlCursor *cursor,
+                                       gint                 column)
+{
+       if (tracker_sparql_cursor_get_value_type (cursor, column) == TRACKER_SPARQL_VALUE_TYPE_DOUBLE) {
+               const gchar *text;
+
+               text = tracker_sparql_cursor_get_string (cursor, column, NULL);
+               return g_ascii_strtod (text, NULL);
+       }
+
+       return 0.0;
+}
+
+static gboolean
+tracker_sparql_cursor_real_get_boolean (TrackerSparqlCursor *cursor,
+                                        gint                 column)
+{
+       if (tracker_sparql_cursor_get_value_type (cursor, column) == TRACKER_SPARQL_VALUE_TYPE_BOOLEAN) {
+               const gchar *text;
+
+               text = tracker_sparql_cursor_get_string (cursor, column, NULL);
+               return g_ascii_strcasecmp (text, "true") == 0;
+       }
+
+       return FALSE;
+}
+
+static gboolean
+tracker_sparql_cursor_real_is_bound (TrackerSparqlCursor *cursor,
+                                     gint                 column)
+{
+       return tracker_sparql_cursor_get_value_type (cursor, column) != TRACKER_SPARQL_VALUE_TYPE_UNBOUND;
+}
+
+static void
+tracker_sparql_cursor_finalize (GObject *object)
+{
+       TrackerSparqlCursor *cursor = TRACKER_SPARQL_CURSOR (object);
+       TrackerSparqlCursorPrivate *priv = tracker_sparql_cursor_get_instance_private (cursor);
+
+       g_clear_object (&priv->connection);
+       G_OBJECT_CLASS (tracker_sparql_cursor_parent_class)->finalize (object);
+}
+
+static void
+tracker_sparql_cursor_set_property (GObject      *object,
+                                    guint         prop_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+       TrackerSparqlCursor *cursor = TRACKER_SPARQL_CURSOR (object);
+       TrackerSparqlCursorPrivate *priv = tracker_sparql_cursor_get_instance_private (cursor);
+
+       switch (prop_id) {
+       case PROP_CONNECTION:
+               priv->connection = g_value_dup_object (value);
+               break;
+       case PROP_N_COLUMNS:
+               priv->n_columns = g_value_get_int (value);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       }
+}
+
+static void
+tracker_sparql_cursor_get_property (GObject    *object,
+                                    guint       prop_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+       TrackerSparqlCursor *cursor = TRACKER_SPARQL_CURSOR (object);
+       TrackerSparqlCursorPrivate *priv = tracker_sparql_cursor_get_instance_private (cursor);
+
+       switch (prop_id) {
+       case PROP_CONNECTION:
+               g_value_set_object (value, priv->connection);
+               break;
+       case PROP_N_COLUMNS:
+               g_value_set_int (value, priv->n_columns);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       }
+}
+
+static void
+tracker_sparql_cursor_class_init (TrackerSparqlCursorClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = tracker_sparql_cursor_finalize;
+       object_class->set_property = tracker_sparql_cursor_set_property;
+       object_class->get_property = tracker_sparql_cursor_get_property;
+
+       klass->get_integer = tracker_sparql_cursor_real_get_integer;
+       klass->get_double = tracker_sparql_cursor_real_get_double;
+       klass->get_boolean = tracker_sparql_cursor_real_get_boolean;
+       klass->is_bound = tracker_sparql_cursor_real_is_bound;
+
+       /**
+        * TrackerSparqlCursor:connection:
+        *
+        * The #TrackerSparqlConnection used to retrieve the results.
+        */
+       props[PROP_CONNECTION] =
+               g_param_spec_object ("connection",
+                                    "connection",
+                                    "connection",
+                                    TRACKER_SPARQL_TYPE_CONNECTION,
+                                    G_PARAM_CONSTRUCT_ONLY |
+                                    G_PARAM_STATIC_STRINGS |
+                                    G_PARAM_READABLE |
+                                    G_PARAM_WRITABLE);
+       /**
+        * TrackerSparqlCursor:n_columns:
+        *
+        * Number of columns available in the results to iterate.
+        */
+       props[PROP_N_COLUMNS] =
+               g_param_spec_int ("n-columns",
+                                 "n-columns",
+                                 "n-columns",
+                                 G_MININT, G_MAXINT, 0,
+                                 G_PARAM_STATIC_STRINGS |
+                                 G_PARAM_READABLE);
+
+       g_object_class_install_properties (object_class, N_PROPS, props);
+}
+
+/**
+ * tracker_sparql_cursor_get_connection:
+ * @cursor: a #TrackerSparqlCursor
+ *
+ * Returns: (transfer none): the #TrackerSparqlConnection associated with this
+ * #TrackerSparqlCursor. The returned object must not be unreferenced
+ * by the caller.
+ */
+TrackerSparqlConnection *
+tracker_sparql_cursor_get_connection (TrackerSparqlCursor *cursor)
+{
+       TrackerSparqlCursorPrivate *priv = tracker_sparql_cursor_get_instance_private (cursor);
+
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor), NULL);
+
+       return priv->connection;
+}
+
+void
+tracker_sparql_cursor_set_connection (TrackerSparqlCursor     *cursor,
+                                      TrackerSparqlConnection *connection)
+{
+       TrackerSparqlCursorPrivate *priv = tracker_sparql_cursor_get_instance_private (cursor);
+
+       g_return_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor));
+       g_return_if_fail (TRACKER_IS_SPARQL_CONNECTION (connection));
+
+       g_set_object (&priv->connection, connection);
+}
+
+/**
+ * tracker_sparql_cursor_get_n_columns:
+ * @cursor: a #TrackerSparqlCursor
+ *
+ * This method should only be called after a successful
+ * tracker_sparql_cursor_next(); otherwise its return value
+ * will be undefined.
+ *
+ * Returns: a #gint representing the number of columns available in the
+ * results to iterate.
+ */
+gint
+tracker_sparql_cursor_get_n_columns (TrackerSparqlCursor *cursor)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor), 0);
+
+       return TRACKER_SPARQL_CURSOR_GET_CLASS (cursor)->get_n_columns (cursor);
+}
+
+/**
+ * tracker_sparql_cursor_get_string:
+ * @cursor: a #TrackerSparqlCursor
+ * @column: column number to retrieve (first one is 0)
+ * @length: length of the returned string
+ *
+ * Retrieves a string representation of the data in the current
+ * row in @column.
+ *
+ * Returns: a string which must not be freed. %NULL is returned if
+ * the column is not in the [0,#n_columns] range.
+ */
+const gchar *
+tracker_sparql_cursor_get_string (TrackerSparqlCursor *cursor,
+                                  gint                 column,
+                                  glong               *length)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor), NULL);
+
+       return TRACKER_SPARQL_CURSOR_GET_CLASS (cursor)->get_string (cursor,
+                                                                    column,
+                                                                    length);
+}
+
+/**
+ * tracker_sparql_cursor_get_boolean:
+ * @cursor: a #TrackerSparqlCursor
+ * @column: column number to retrieve (first one is 0)
+ *
+ * Retrieve a boolean for the current row in @column.
+ *
+ * Returns: a #gboolean.
+ */
+gboolean
+tracker_sparql_cursor_get_boolean (TrackerSparqlCursor *cursor,
+                                   gint                 column)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor), FALSE);
+
+       return TRACKER_SPARQL_CURSOR_GET_CLASS (cursor)->get_boolean (cursor,
+                                                                     column);
+}
+
+/**
+ * tracker_sparql_cursor_get_double:
+ * @cursor: a #TrackerSparqlCursor
+ * @column: column number to retrieve (first one is 0)
+ *
+ * Retrieve a double for the current row in @column.
+ *
+ * Returns: a double.
+ */
+gdouble
+tracker_sparql_cursor_get_double (TrackerSparqlCursor *cursor,
+                                  gint                 column)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor), -1);
+
+       return TRACKER_SPARQL_CURSOR_GET_CLASS (cursor)->get_double (cursor,
+                                                                    column);
+}
+
+/**
+ * tracker_sparql_cursor_get_integer:
+ * @cursor: a #TrackerSparqlCursor
+ * @column: column number to retrieve (first one is 0)
+ *
+ * Retrieve an integer for the current row in @column.
+ *
+ * Returns: a #gint64.
+ */
+gint64
+tracker_sparql_cursor_get_integer (TrackerSparqlCursor *cursor,
+                                   gint                 column)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor), -1);
+
+       return TRACKER_SPARQL_CURSOR_GET_CLASS (cursor)->get_integer (cursor,
+                                                                     column);
+}
+
+/**
+ * tracker_sparql_cursor_get_value_type:
+ * @cursor: a #TrackerSparqlCursor
+ * @column: column number to retrieve (first one is 0)
+ *
+ * The data type bound to the current row in @column is returned.
+ *
+ * Returns: a #TrackerSparqlValueType.
+ */
+TrackerSparqlValueType
+tracker_sparql_cursor_get_value_type (TrackerSparqlCursor *cursor,
+                                      gint                 column)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor),
+                             TRACKER_SPARQL_VALUE_TYPE_UNBOUND);
+
+       return TRACKER_SPARQL_CURSOR_GET_CLASS (cursor)->get_value_type (cursor,
+                                                                        column);
+}
+
+/**
+ * tracker_sparql_cursor_get_variable_name:
+ * @cursor: a #TrackerSparqlCursor
+ * @column: column number to retrieve (first one is 0)
+ *
+ * Retrieves the variable name for the current row in @column.
+ *
+ * Returns: a string which must not be freed.
+ */
+const gchar *
+tracker_sparql_cursor_get_variable_name (TrackerSparqlCursor *cursor,
+                                         gint                 column)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor), NULL);
+
+       return TRACKER_SPARQL_CURSOR_GET_CLASS (cursor)->get_variable_name (cursor,
+                                                                           column);
+}
+
+/**
+ * tracker_sparql_cursor_close:
+ * @cursor: a #TrackerSparqlCursor
+ *
+ * Closes the iterator, making it invalid.
+ */
+void
+tracker_sparql_cursor_close (TrackerSparqlCursor *cursor)
+{
+       g_return_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor));
+
+       return TRACKER_SPARQL_CURSOR_GET_CLASS (cursor)->close (cursor);
+}
+
+/**
+ * tracker_sparql_cursor_is_bound:
+ * @cursor: a #TrackerSparqlCursor
+ * @column: column number to retrieve (first one is 0)
+ *
+ * If the current row and @column are bound to a value, %TRUE is returned.
+ *
+ * Returns: a %TRUE or %FALSE.
+ */
+gboolean
+tracker_sparql_cursor_is_bound (TrackerSparqlCursor *cursor,
+                                gint                 column)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor), FALSE);
+
+       return TRACKER_SPARQL_CURSOR_GET_CLASS (cursor)->is_bound (cursor, column);
+}
+
+/**
+ * tracker_sparql_cursor_next:
+ * @cursor: a #TrackerSparqlCursor
+ * @cancellable: a #GCancellable used to cancel the operation
+ * @error: #GError for error reporting.
+ *
+ * Iterates to the next result. This is completely synchronous and
+ * it may block.
+ *
+ * Returns: %FALSE if no more results found, otherwise %TRUE.
+ */
+gboolean
+tracker_sparql_cursor_next (TrackerSparqlCursor  *cursor,
+                            GCancellable         *cancellable,
+                            GError              **error)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor), FALSE);
+       g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
+       g_return_val_if_fail (!error || !*error, FALSE);
+
+       return TRACKER_SPARQL_CURSOR_GET_CLASS (cursor)->next (cursor,
+                                                              cancellable,
+                                                              error);
+}
+
+/**
+ * tracker_sparql_cursor_next_async:
+ * @cursor: a #TrackerSparqlCursor
+ * @cancellable: a #GCancellable used to cancel the operation
+ * @callback: user-defined #GAsyncReadyCallback to be called when
+ *            asynchronous operation is finished.
+ * @user_data: user-defined data to be passed to @callback
+ *
+ * Iterates, asynchronously, to the next result.
+ */
+void
+tracker_sparql_cursor_next_async (TrackerSparqlCursor  *cursor,
+                                  GCancellable         *cancellable,
+                                  GAsyncReadyCallback   callback,
+                                  gpointer              user_data)
+{
+       g_return_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor));
+       g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+       return TRACKER_SPARQL_CURSOR_GET_CLASS (cursor)->next_async (cursor,
+                                                                    cancellable,
+                                                                    callback,
+                                                                    user_data);
+}
+
+/**
+ * tracker_sparql_cursor_next_finish:
+ * @cursor: a #TrackerSparqlCursor
+ * @res: a #GAsyncResult with the result of the operation
+ * @error: #GError for error reporting.
+ *
+ * Finishes the asynchronous iteration to the next result.
+ *
+ * Returns: %FALSE if no more results found, otherwise %TRUE.
+ */
+gboolean
+tracker_sparql_cursor_next_finish (TrackerSparqlCursor  *cursor,
+                                   GAsyncResult         *res,
+                                   GError              **error)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
+       g_return_val_if_fail (!error || !*error, FALSE);
+
+       return TRACKER_SPARQL_CURSOR_GET_CLASS (cursor)->next_finish (cursor,
+                                                                     res,
+                                                                     error);
+}
+
+/**
+ * tracker_sparql_cursor_rewind:
+ * @cursor: a #TrackerSparqlCursor
+ *
+ * Resets the iterator to point back to the first result.
+ */
+void
+tracker_sparql_cursor_rewind (TrackerSparqlCursor *cursor)
+{
+       g_return_if_fail (TRACKER_IS_SPARQL_CURSOR (cursor));
+
+       return TRACKER_SPARQL_CURSOR_GET_CLASS (cursor)->rewind (cursor);
+}
diff --git a/src/libtracker-sparql/tracker-cursor.h b/src/libtracker-sparql/tracker-cursor.h
new file mode 100644
index 000000000..7016b01f2
--- /dev/null
+++ b/src/libtracker-sparql/tracker-cursor.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2010, Nokia <ivan frade nokia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+#ifndef __TRACKER_SPARQL_CURSOR_H__
+#define __TRACKER_SPARQL_CURSOR_H__
+
+#if !defined (__LIBTRACKER_SPARQL_INSIDE__) && !defined (TRACKER_COMPILATION)
+#error "only <libtracker-sparql/tracker-sparql.h> must be included directly."
+#endif
+
+#include <gio/gio.h>
+
+/**
+ * TrackerSparqlCursor:
+ *
+ * The <structname>TrackerSparqlCursor</structname> object represents an
+ * iterator of results.
+ */
+#define TRACKER_TYPE_SPARQL_CURSOR tracker_sparql_cursor_get_type ()
+#define TRACKER_SPARQL_TYPE_CURSOR TRACKER_TYPE_SPARQL_CURSOR
+G_DECLARE_DERIVABLE_TYPE (TrackerSparqlCursor, tracker_sparql_cursor,
+                          TRACKER, SPARQL_CURSOR, GObject)
+
+#include "tracker-connection.h"
+
+/**
+ * TrackerSparqlValueType:
+ * @TRACKER_SPARQL_VALUE_TYPE_UNBOUND: Unbound value type
+ * @TRACKER_SPARQL_VALUE_TYPE_URI: Uri value type, rdfs:Resource
+ * @TRACKER_SPARQL_VALUE_TYPE_STRING: String value type, xsd:string
+ * @TRACKER_SPARQL_VALUE_TYPE_INTEGER: Integer value type, xsd:integer
+ * @TRACKER_SPARQL_VALUE_TYPE_DOUBLE: Double value type, xsd:double
+ * @TRACKER_SPARQL_VALUE_TYPE_DATETIME: Datetime value type, xsd:dateTime
+ * @TRACKER_SPARQL_VALUE_TYPE_BLANK_NODE: Blank node value type
+ * @TRACKER_SPARQL_VALUE_TYPE_BOOLEAN: Boolean value type, xsd:boolean
+ *
+ * Enumeration with the possible types of the cursor's cells
+ */
+typedef enum {
+       TRACKER_SPARQL_VALUE_TYPE_UNBOUND,
+       TRACKER_SPARQL_VALUE_TYPE_URI,
+       TRACKER_SPARQL_VALUE_TYPE_STRING,
+       TRACKER_SPARQL_VALUE_TYPE_INTEGER,
+       TRACKER_SPARQL_VALUE_TYPE_DOUBLE,
+       TRACKER_SPARQL_VALUE_TYPE_DATETIME,
+       TRACKER_SPARQL_VALUE_TYPE_BLANK_NODE,
+       TRACKER_SPARQL_VALUE_TYPE_BOOLEAN,
+} TrackerSparqlValueType;
+
+struct _TrackerSparqlCursorClass
+{
+       GObjectClass parent_class;
+
+       TrackerSparqlValueType (* get_value_type) (TrackerSparqlCursor *cursor,
+                                                  gint                 column);
+        const gchar* (* get_variable_name) (TrackerSparqlCursor *cursor,
+                                            gint                 column);
+       const gchar* (* get_string) (TrackerSparqlCursor *cursor,
+                                    gint                 column,
+                                    glong               *length);
+        gboolean (* next) (TrackerSparqlCursor  *cursor,
+                           GCancellable         *cancellable,
+                           GError              **error);
+        void (* next_async) (TrackerSparqlCursor *cursor,
+                             GCancellable        *cancellable,
+                             GAsyncReadyCallback  callback,
+                             gpointer             user_data);
+        gboolean (* next_finish) (TrackerSparqlCursor  *cursor,
+                                  GAsyncResult         *res,
+                                  GError              **error);
+        void (* rewind) (TrackerSparqlCursor* cursor);
+        void (* close) (TrackerSparqlCursor* cursor);
+        gint64 (* get_integer) (TrackerSparqlCursor *cursor,
+                                gint                 column);
+        gdouble (* get_double) (TrackerSparqlCursor *cursor,
+                                gint                 column);
+        gboolean (* get_boolean) (TrackerSparqlCursor *cursor,
+                                  gint                 column);
+        gboolean (* is_bound) (TrackerSparqlCursor *cursor,
+                               gint                 column);
+        gint (* get_n_columns) (TrackerSparqlCursor *cursor);
+};
+
+TrackerSparqlConnection * tracker_sparql_cursor_get_connection (TrackerSparqlCursor *cursor);
+gint tracker_sparql_cursor_get_n_columns (TrackerSparqlCursor *cursor);
+
+const gchar * tracker_sparql_cursor_get_string (TrackerSparqlCursor *cursor,
+                                                gint                 column,
+                                                glong               *length);
+gboolean tracker_sparql_cursor_get_boolean (TrackerSparqlCursor *cursor,
+                                            gint                 column);
+gdouble tracker_sparql_cursor_get_double (TrackerSparqlCursor *cursor,
+                                          gint                 column);
+gint64 tracker_sparql_cursor_get_integer (TrackerSparqlCursor *cursor,
+                                          gint                 column);
+TrackerSparqlValueType tracker_sparql_cursor_get_value_type (TrackerSparqlCursor *cursor,
+                                                             gint                 column);
+const gchar * tracker_sparql_cursor_get_variable_name (TrackerSparqlCursor *cursor,
+                                                       gint                 column);
+void tracker_sparql_cursor_close (TrackerSparqlCursor *cursor);
+
+gboolean tracker_sparql_cursor_is_bound (TrackerSparqlCursor *cursor,
+                                         gint                 column);
+
+gboolean tracker_sparql_cursor_next (TrackerSparqlCursor  *cursor,
+                                     GCancellable         *cancellable,
+                                     GError              **error);
+
+void tracker_sparql_cursor_next_async (TrackerSparqlCursor  *cursor,
+                                       GCancellable         *cancellable,
+                                       GAsyncReadyCallback   callback,
+                                       gpointer              user_data);
+
+gboolean tracker_sparql_cursor_next_finish (TrackerSparqlCursor  *cursor,
+                                            GAsyncResult         *res,
+                                            GError              **error);
+
+void tracker_sparql_cursor_rewind (TrackerSparqlCursor *cursor);
+
+#endif /* __TRACKER_SPARQL_CURSOR_H__ */
diff --git a/src/libtracker-sparql/tracker-endpoint-dbus.c b/src/libtracker-sparql/tracker-endpoint-dbus.c
index d4471f7e1..53f08b431 100644
--- a/src/libtracker-sparql/tracker-endpoint-dbus.c
+++ b/src/libtracker-sparql/tracker-endpoint-dbus.c
@@ -22,6 +22,7 @@
 #include "config.h"
 
 #include "tracker-endpoint-dbus.h"
+#include "tracker-notifier.h"
 
 #include <gio/gio.h>
 #include <gio/gunixinputstream.h>
@@ -642,7 +643,7 @@ tracker_endpoint_dbus_new (TrackerSparqlConnection  *sparql_connection,
                            GCancellable             *cancellable,
                            GError                  **error)
 {
-       g_return_val_if_fail (TRACKER_SPARQL_IS_CONNECTION (sparql_connection), NULL);
+       g_return_val_if_fail (TRACKER_IS_SPARQL_CONNECTION (sparql_connection), NULL);
        g_return_val_if_fail (G_IS_DBUS_CONNECTION (dbus_connection), NULL);
        g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL);
        g_return_val_if_fail (!error || !*error, NULL);
diff --git a/src/libtracker-sparql/tracker-endpoint.h b/src/libtracker-sparql/tracker-endpoint.h
index d665b74da..580e9f7e8 100644
--- a/src/libtracker-sparql/tracker-endpoint.h
+++ b/src/libtracker-sparql/tracker-endpoint.h
@@ -27,7 +27,7 @@
 #endif
 
 #include <glib-object.h>
-#include <libtracker-sparql/tracker-generated.h>
+#include <libtracker-sparql/tracker-connection.h>
 
 #define TRACKER_TYPE_ENDPOINT tracker_endpoint_get_type()
 G_DECLARE_DERIVABLE_TYPE (TrackerEndpoint, tracker_endpoint, TRACKER, ENDPOINT, GObject)
diff --git a/src/libtracker-sparql/tracker-notifier.c b/src/libtracker-sparql/tracker-notifier.c
index e7f5f8b01..c0c90db95 100644
--- a/src/libtracker-sparql/tracker-notifier.c
+++ b/src/libtracker-sparql/tracker-notifier.c
@@ -65,10 +65,10 @@
 
 #include "config.h"
 
+#include "tracker-connection.h"
 #include "tracker-notifier.h"
 #include "tracker-notifier-private.h"
 #include "tracker-sparql-enum-types.h"
-#include "tracker-generated-no-checks.h"
 #include <libtracker-common/tracker-common.h>
 
 typedef struct _TrackerNotifierPrivate TrackerNotifierPrivate;
@@ -509,6 +509,8 @@ tracker_notifier_class_init (TrackerNotifierClass *klass)
        /**
         * TrackerNotifier::events:
         * @self: The #TrackerNotifier
+        * @service: The SPARQL service that originated the events, %NULL for the local store
+        * @graph: The graph where the events happened on, %NULL for the default anonymous graph
         * @events: (element-type TrackerNotifierEvent): A #GPtrArray of #TrackerNotifierEvent
         *
         * Notifies of changes in the Tracker database.
diff --git a/src/libtracker-sparql/tracker-namespace.vala b/src/libtracker-sparql/tracker-private.h
similarity index 67%
rename from src/libtracker-sparql/tracker-namespace.vala
rename to src/libtracker-sparql/tracker-private.h
index a587a47fa..9aa2d109c 100644
--- a/src/libtracker-sparql/tracker-namespace.vala
+++ b/src/libtracker-sparql/tracker-private.h
@@ -1,5 +1,6 @@
 /*
- * Copyright © 2015 Collabora Ltd.
+ * Copyright (C) 2010, Nokia <ivan frade nokia com>
+ * Copyright (C) 2019, Red Hat Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -16,14 +17,12 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA  02110-1301, USA.
  */
+#ifndef __TRACKER_PRIVATE_H__
+#define __TRACKER_PRIVATE_H__
 
-/*
- * This file serves as the representation for the Tracker namespace, mostly
- * so that we can set its namespace and version attributes for GIR.
- */
+#include "tracker-cursor.h"
+
+void tracker_sparql_cursor_set_connection (TrackerSparqlCursor     *cursor,
+                                           TrackerSparqlConnection *connection);
 
-[CCode (cprefix = "Tracker", gir_namespace = "Tracker",
-        gir_version = "2.0", lower_case_cprefix = "tracker_")]
-namespace Tracker
-{
-}
+#endif /* __TRACKER_PRIVATE_H__ */
diff --git a/src/libtracker-sparql/tracker-resource.c b/src/libtracker-sparql/tracker-resource.c
index 03b45991e..c0a4aa3fe 100644
--- a/src/libtracker-sparql/tracker-resource.c
+++ b/src/libtracker-sparql/tracker-resource.c
@@ -29,7 +29,7 @@
 #include <tracker-ontologies.h>
 
 /* For tracker_sparql_escape_string */
-#include "tracker-generated-no-checks.h"
+#include "tracker-utils.h"
 
 typedef struct {
        char *identifier;
diff --git a/src/libtracker-sparql/tracker-sparql.h b/src/libtracker-sparql/tracker-sparql.h
index a87122e4d..8555fb891 100644
--- a/src/libtracker-sparql/tracker-sparql.h
+++ b/src/libtracker-sparql/tracker-sparql.h
@@ -22,13 +22,17 @@
 
 #define __LIBTRACKER_SPARQL_INSIDE__
 
+#include <libtracker-sparql/tracker-connection.h>
+#include <libtracker-sparql/tracker-cursor.h>
 #include <libtracker-sparql/tracker-endpoint.h>
 #include <libtracker-sparql/tracker-endpoint-dbus.h>
 #include <libtracker-sparql/tracker-version.h>
 #include <libtracker-sparql/tracker-ontologies.h>
 #include <libtracker-sparql/tracker-resource.h>
+#include <libtracker-sparql/tracker-statement.h>
 #include <libtracker-sparql/tracker-notifier.h>
-#include <libtracker-sparql/tracker-generated.h>
+#include <libtracker-sparql/tracker-sparql-enum-types.h>
+#include <libtracker-sparql/tracker-utils.h>
 
 #undef __LIBTRACKER_SPARQL_INSIDE__
 
diff --git a/src/libtracker-sparql/tracker-statement.c b/src/libtracker-sparql/tracker-statement.c
new file mode 100644
index 000000000..e46e0825e
--- /dev/null
+++ b/src/libtracker-sparql/tracker-statement.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2018, Red Hat Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+/**
+ * SECTION: tracker-sparql-statement
+ * @short_description: Prepared statements
+ * @title: TrackerSparqlStatement
+ * @stability: Stable
+ * @include: tracker-sparql.h
+ *
+ * The <structname>TrackerSparqlStatement</structname> object represents
+ * a SPARQL query. This query may contain parameterized variables
+ * (expressed as ~var in the syntax), which may be mapped to arbitrary
+ * values prior to execution. This statement may be reused for future
+ * queries with different values.
+ *
+ * The argument bindings may be changed through tracker_sparql_statement_bind_int(),
+ * tracker_sparql_statement_bind_boolean(), tracker_sparql_statement_bind_double()
+ * and tracker_sparql_statement_bind_string(). Those functions receive
+ * a @name argument corresponding for the variable name in the SPARQL query
+ * (eg. "var" for ~var) and a @value to map the variable to.
+ *
+ * Once all arguments have a value, the query may be executed through
+ * tracker_sparql_statement_execute() or tracker_sparql_statement_execute_async().
+ *
+ * This object was added in Tracker 2.2.
+ */
+#include "config.h"
+
+#include "tracker-statement.h"
+
+enum {
+       PROP_0,
+       PROP_CONNECTION,
+       PROP_SPARQL,
+       N_PROPS
+};
+
+static GParamSpec *props[N_PROPS];
+
+typedef struct {
+       TrackerSparqlConnection *connection;
+       gchar *sparql;
+} TrackerSparqlStatementPrivate;
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (TrackerSparqlStatement,
+                                     tracker_sparql_statement,
+                                     G_TYPE_OBJECT)
+
+static void
+tracker_sparql_statement_init (TrackerSparqlStatement *stmt)
+{
+}
+
+static void
+tracker_sparql_statement_finalize (GObject *object)
+{
+       TrackerSparqlStatement *stmt = TRACKER_SPARQL_STATEMENT (object);
+       TrackerSparqlStatementPrivate *priv = tracker_sparql_statement_get_instance_private (stmt);
+
+       g_clear_object (&priv->connection);
+       g_free (priv->sparql);
+       G_OBJECT_CLASS (tracker_sparql_statement_parent_class)->finalize (object);
+}
+
+static void
+tracker_sparql_statement_set_property (GObject      *object,
+                                       guint         prop_id,
+                                       const GValue *value,
+                                       GParamSpec   *pspec)
+{
+       TrackerSparqlStatement *stmt = TRACKER_SPARQL_STATEMENT (object);
+       TrackerSparqlStatementPrivate *priv = tracker_sparql_statement_get_instance_private (stmt);
+
+       switch (prop_id) {
+       case PROP_CONNECTION:
+               priv->connection = g_value_dup_object (value);
+               break;
+       case PROP_SPARQL:
+               priv->sparql = g_value_dup_string (value);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       }
+}
+
+static void
+tracker_sparql_statement_get_property (GObject    *object,
+                                       guint       prop_id,
+                                       GValue     *value,
+                                       GParamSpec *pspec)
+{
+       TrackerSparqlStatement *stmt = TRACKER_SPARQL_STATEMENT (object);
+       TrackerSparqlStatementPrivate *priv = tracker_sparql_statement_get_instance_private (stmt);
+
+       switch (prop_id) {
+       case PROP_CONNECTION:
+               g_value_set_object (value, priv->connection);
+               break;
+       case PROP_SPARQL:
+               g_value_set_string (value, priv->sparql);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       }
+}
+
+static void
+tracker_sparql_statement_class_init (TrackerSparqlStatementClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = tracker_sparql_statement_finalize;
+       object_class->set_property = tracker_sparql_statement_set_property;
+       object_class->get_property = tracker_sparql_statement_get_property;
+
+       /**
+        * TrackerSparqlStatement:connection:
+        *
+        * The #TrackerSparqlConnection used to perform the query.
+        */
+       props[PROP_CONNECTION] =
+               g_param_spec_object ("connection",
+                                    "connection",
+                                    "connection",
+                                    TRACKER_TYPE_SPARQL_CONNECTION,
+                                    G_PARAM_CONSTRUCT_ONLY |
+                                    G_PARAM_STATIC_STRINGS |
+                                    G_PARAM_READABLE |
+                                    G_PARAM_WRITABLE);
+       /**
+        * TrackerSparqlStatement:sparql:
+        *
+        * SPARQL query stored in this statement.
+        */
+       props[PROP_SPARQL] =
+               g_param_spec_string ("sparql",
+                                    "sparql",
+                                    "sparql",
+                                    NULL,
+                                    G_PARAM_CONSTRUCT_ONLY |
+                                    G_PARAM_STATIC_STRINGS |
+                                    G_PARAM_READABLE |
+                                    G_PARAM_WRITABLE);
+
+       g_object_class_install_properties (object_class, N_PROPS, props);
+}
+
+TrackerSparqlConnection *
+tracker_sparql_statement_get_connection (TrackerSparqlStatement *stmt)
+{
+       TrackerSparqlStatementPrivate *priv = tracker_sparql_statement_get_instance_private (stmt);
+
+       g_return_val_if_fail (TRACKER_IS_SPARQL_STATEMENT (stmt), NULL);
+
+       return priv->connection;
+}
+
+const gchar *
+tracker_sparql_statement_get_sparql (TrackerSparqlStatement *stmt)
+{
+       TrackerSparqlStatementPrivate *priv = tracker_sparql_statement_get_instance_private (stmt);
+
+       g_return_val_if_fail (TRACKER_IS_SPARQL_STATEMENT (stmt), NULL);
+
+       return priv->sparql;
+}
+
+/**
+ * tracker_sparql_statement_bind_boolean:
+ * @stmt: a #TrackerSparqlStatement
+ * @name: variable name
+ * @value: value
+ *
+ * Binds the boolean @value to variable @name.
+ */
+void
+tracker_sparql_statement_bind_boolean (TrackerSparqlStatement *stmt,
+                                       const gchar            *name,
+                                       gboolean                value)
+{
+       g_return_if_fail (TRACKER_IS_SPARQL_STATEMENT (stmt));
+       g_return_if_fail (name != NULL);
+
+       return TRACKER_SPARQL_STATEMENT_GET_CLASS (stmt)->bind_boolean (stmt,
+                                                                       name,
+                                                                       value);
+}
+
+/**
+ * tracker_sparql_statement_bind_int:
+ * @stmt: a #TrackerSparqlStatement
+ * @name: variable name
+ * @value: value
+ *
+ * Binds the integer @value to variable @name.
+ */
+void
+tracker_sparql_statement_bind_int (TrackerSparqlStatement *stmt,
+                                   const gchar            *name,
+                                   gint64                  value)
+{
+       g_return_if_fail (TRACKER_IS_SPARQL_STATEMENT (stmt));
+       g_return_if_fail (name != NULL);
+
+       return TRACKER_SPARQL_STATEMENT_GET_CLASS (stmt)->bind_int (stmt,
+                                                                   name,
+                                                                   value);
+}
+
+/**
+ * tracker_sparql_statement_bind_double:
+ * @stmt: a #TrackerSparqlStatement
+ * @name: variable name
+ * @value: value
+ *
+ * Binds the double @value to variable @name.
+ */
+void
+tracker_sparql_statement_bind_double (TrackerSparqlStatement *stmt,
+                                      const gchar            *name,
+                                      gdouble                 value)
+{
+       g_return_if_fail (TRACKER_IS_SPARQL_STATEMENT (stmt));
+       g_return_if_fail (name != NULL);
+
+       return TRACKER_SPARQL_STATEMENT_GET_CLASS (stmt)->bind_double (stmt,
+                                                                      name,
+                                                                      value);
+}
+
+/**
+ * tracker_sparql_statement_bind_string:
+ * @stmt: a #TrackerSparqlStatement
+ * @name: variable name
+ * @value: value
+ *
+ * Binds the string @value to variable @name.
+ */
+void
+tracker_sparql_statement_bind_string (TrackerSparqlStatement *stmt,
+                                      const gchar            *name,
+                                      const gchar            *value)
+{
+       g_return_if_fail (TRACKER_IS_SPARQL_STATEMENT (stmt));
+       g_return_if_fail (name != NULL);
+       g_return_if_fail (value != NULL);
+
+       return TRACKER_SPARQL_STATEMENT_GET_CLASS (stmt)->bind_string (stmt,
+                                                                      name,
+                                                                      value);
+}
+
+/**
+ * tracker_sparql_statement_execute:
+ * @stmt: a #TrackerSparqlStatement
+ * @cancellable: a #GCancellable used to cancel the operation
+ * @error: #GError for error reporting.
+ *
+ * Executes the SPARQL query with the currently bound values.
+ *
+ * Returns: (transfer full): A #TrackerSparqlCursor
+ */
+TrackerSparqlCursor *
+tracker_sparql_statement_execute (TrackerSparqlStatement  *stmt,
+                                  GCancellable            *cancellable,
+                                  GError                 **error)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_STATEMENT (stmt), NULL);
+       g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL);
+       g_return_val_if_fail (!error || !*error, NULL);
+
+       return TRACKER_SPARQL_STATEMENT_GET_CLASS (stmt)->execute (stmt,
+                                                                  cancellable,
+                                                                  error);
+}
+
+/**
+ * tracker_sparql_statement_execute_async:
+ * @stmt: a #TrackerSparqlStatement
+ * @cancellable: a #GCancellable used to cancel the operation
+ * @callback: user-defined #GAsyncReadyCallback to be called when
+ *            asynchronous operation is finished.
+ * @user_data: user-defined data to be passed to @callback
+ *
+ * Asynchronously executes the SPARQL query with the currently bound values.
+ */
+void
+tracker_sparql_statement_execute_async (TrackerSparqlStatement *stmt,
+                                        GCancellable           *cancellable,
+                                        GAsyncReadyCallback     callback,
+                                        gpointer                user_data)
+{
+       g_return_if_fail (TRACKER_IS_SPARQL_STATEMENT (stmt));
+       g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+       return TRACKER_SPARQL_STATEMENT_GET_CLASS (stmt)->execute_async (stmt,
+                                                                        cancellable,
+                                                                        callback,
+                                                                        user_data);
+}
+
+/**
+ * tracker_sparql_statement_execute_finish:
+ * @stmt: a #TrackerSparqlStatement
+ * @res: The #GAsyncResult from the callback used to return the #TrackerSparqlCursor
+ * @error: The error which occurred or %NULL
+ *
+ * Finishes the asynchronous operation started through
+ * tracker_sparql_statement_execute_async().
+ *
+ * Returns: (transfer full): A #TrackerSparqlCursor
+ */
+TrackerSparqlCursor *
+tracker_sparql_statement_execute_finish (TrackerSparqlStatement  *stmt,
+                                         GAsyncResult            *res,
+                                         GError                 **error)
+{
+       g_return_val_if_fail (TRACKER_IS_SPARQL_STATEMENT (stmt), NULL);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
+       g_return_val_if_fail (!error || !*error, NULL);
+
+       return TRACKER_SPARQL_STATEMENT_GET_CLASS (stmt)->execute_finish (stmt,
+                                                                         res,
+                                                                         error);
+}
+
+/**
+ * tracker_sparql_statement_clear_bindings:
+ * @self: a #TrackerSparqlStatement
+ *
+ * Clears all boolean/string/integer/double bindings.
+ *
+ * Since: 3.0
+ */
+void
+tracker_sparql_statement_clear_bindings (TrackerSparqlStatement *stmt)
+{
+       g_return_if_fail (TRACKER_IS_SPARQL_STATEMENT (stmt));
+
+       TRACKER_SPARQL_STATEMENT_GET_CLASS (stmt)->clear_bindings (stmt);
+}
diff --git a/src/libtracker-sparql/tracker-statement.h b/src/libtracker-sparql/tracker-statement.h
new file mode 100644
index 000000000..128e6bc09
--- /dev/null
+++ b/src/libtracker-sparql/tracker-statement.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2018, Red Hat Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+#ifndef __TRACKER_SPARQL_STATEMENT_H__
+#define __TRACKER_SPARQL_STATEMENT_H__
+
+#if !defined (__LIBTRACKER_SPARQL_INSIDE__) && !defined (TRACKER_COMPILATION)
+#error "only <libtracker-sparql/tracker-sparql.h> must be included directly."
+#endif
+
+#include <gio/gio.h>
+
+#define TRACKER_TYPE_SPARQL_STATEMENT tracker_sparql_statement_get_type ()
+#define TRACKER_SPARQL_TYPE_STATEMENT TRACKER_TYPE_SPARQL_STATEMENT
+G_DECLARE_DERIVABLE_TYPE (TrackerSparqlStatement,
+                          tracker_sparql_statement,
+                          TRACKER, SPARQL_STATEMENT,
+                          GObject)
+
+#include "tracker-connection.h"
+#include "tracker-cursor.h"
+
+struct _TrackerSparqlStatementClass
+{
+       GObjectClass parent_class;
+
+        void (* bind_int) (TrackerSparqlStatement *stmt,
+                           const gchar            *name,
+                           gint64                  value);
+        void (* bind_boolean) (TrackerSparqlStatement *stmt,
+                               const gchar            *name,
+                               gboolean                value);
+        void (* bind_string) (TrackerSparqlStatement *stmt,
+                              const gchar            *name,
+                              const gchar            *value);
+        void (* bind_double) (TrackerSparqlStatement *stmt,
+                              const gchar            *name,
+                              gdouble                 value);
+
+        TrackerSparqlCursor * (* execute) (TrackerSparqlStatement  *stmt,
+                                           GCancellable            *cancellable,
+                                           GError                 **error);
+        void (* execute_async) (TrackerSparqlStatement *stmt,
+                                GCancellable           *cancellable,
+                                GAsyncReadyCallback     callback,
+                                gpointer                user_data);
+        TrackerSparqlCursor * (* execute_finish) (TrackerSparqlStatement  *stmt,
+                                                  GAsyncResult            *res,
+                                                  GError                 **error);
+       void (* clear_bindings) (TrackerSparqlStatement *stmt);
+};
+
+TrackerSparqlConnection * tracker_sparql_statement_get_connection (TrackerSparqlStatement *stmt);
+
+const gchar * tracker_sparql_statement_get_sparql (TrackerSparqlStatement *stmt);
+
+void tracker_sparql_statement_bind_boolean (TrackerSparqlStatement *stmt,
+                                            const gchar            *name,
+                                            gboolean                value);
+
+void tracker_sparql_statement_bind_int (TrackerSparqlStatement *stmt,
+                                        const gchar            *name,
+                                        gint64                  value);
+
+void tracker_sparql_statement_bind_double (TrackerSparqlStatement *stmt,
+                                           const gchar            *name,
+                                           gdouble                 value);
+
+void tracker_sparql_statement_bind_string (TrackerSparqlStatement *stmt,
+                                           const gchar            *name,
+                                           const gchar            *value);
+
+TrackerSparqlCursor * tracker_sparql_statement_execute (TrackerSparqlStatement  *stmt,
+                                                        GCancellable            *cancellable,
+                                                        GError                 **error);
+
+void tracker_sparql_statement_execute_async (TrackerSparqlStatement *stmt,
+                                             GCancellable           *cancellable,
+                                             GAsyncReadyCallback     callback,
+                                             gpointer                user_data);
+
+TrackerSparqlCursor * tracker_sparql_statement_execute_finish (TrackerSparqlStatement  *stmt,
+                                                               GAsyncResult            *res,
+                                                               GError                 **error);
+
+void tracker_sparql_statement_clear_bindings (TrackerSparqlStatement *stmt);
+
+#endif /* __TRACKER_SPARQL_STATEMENT_H__ */
diff --git a/src/libtracker-sparql/tracker-uri.c b/src/libtracker-sparql/tracker-uri.c
index 0b5c3f349..b97f84527 100644
--- a/src/libtracker-sparql/tracker-uri.c
+++ b/src/libtracker-sparql/tracker-uri.c
@@ -26,6 +26,7 @@
 #include <glib.h>
 
 #include "tracker-uri.h"
+#include "tracker-utils.h"
 
 /* The TrackerUri GType is useful when encapsulating a URI inside a GValue.
  * When we generate SPARQL we need to treat URIs differently to normal strings
@@ -47,15 +48,6 @@ tracker_uri_get_type (void)
        return g_define_type_id__volatile;
 }
 
-gchar *
-tracker_sparql_escape_uri_vprintf (const gchar *format,
-                                   va_list      args);
-gchar *
-tracker_sparql_escape_uri_printf  (const gchar* format,
-                                   ...);
-gchar *
-tracker_sparql_escape_uri         (const gchar *uri);
-
 static const char *
 find_conversion (const char  *format,
                  const char **after)
diff --git a/src/libtracker-sparql/tracker-utils.c b/src/libtracker-sparql/tracker-utils.c
new file mode 100644
index 000000000..e630b689a
--- /dev/null
+++ b/src/libtracker-sparql/tracker-utils.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010, Nokia <ivan frade nokia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+#include "config.h"
+
+#include "tracker-utils.h"
+
+#include "libtracker-data/tracker-uuid.h"
+
+gchar *
+tracker_sparql_escape_string (const gchar* literal)
+{
+       GString *str;
+       const gchar *p;
+
+       str = g_string_new (NULL);
+       p = literal;
+
+       while (*p != '\0') {
+               size_t len;
+
+               len = strcspn (p, "\t\n\r\b\f\'\"\\");
+               g_string_append_len (str, p, len);
+               p += len;
+
+               switch (*p) {
+               case '\t':
+                       g_string_append (str, "\\t");
+                       break;
+               case '\n':
+                       g_string_append (str, "\\n");
+                       break;
+               case '\r':
+                       g_string_append (str, "\\r");
+                       break;
+               case '\b':
+                       g_string_append (str, "\\b");
+                       break;
+               case '\f':
+                       g_string_append (str, "\\f");
+                       break;
+               case '"':
+                       g_string_append (str, "\\\"");
+                       break;
+               case '\'':
+                       g_string_append (str, "\\'");
+                       break;
+               case '\\':
+                       g_string_append (str, "\\\\");
+                       break;
+               default:
+                       continue;
+               }
+
+               p++;
+       }
+
+       return g_string_free (str, FALSE);
+}
+
+gchar *
+tracker_sparql_get_uuid_urn (void)
+{
+       return tracker_generate_uuid ("urn:uuid");
+}
diff --git a/src/libtracker-sparql/tracker-utils.h b/src/libtracker-sparql/tracker-utils.h
new file mode 100644
index 000000000..2eee4401b
--- /dev/null
+++ b/src/libtracker-sparql/tracker-utils.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010, Nokia <ivan frade nokia com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+#ifndef __TRACKER_UTILS_H__
+#define __TRACKER_UTILS_H__
+
+#include <glib.h>
+
+gchar * tracker_sparql_escape_uri_vprintf (const gchar *format,
+                                           va_list      args);
+gchar * tracker_sparql_escape_uri_printf  (const gchar* format,
+                                           ...);
+gchar * tracker_sparql_escape_uri         (const gchar *uri);
+
+gchar* tracker_sparql_escape_string (const gchar* literal);
+gchar* tracker_sparql_get_uuid_urn (void);
+
+#endif /* __TRACKER_UTILS_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]