[gnome-documents/wip/carlosg/tracker3: 20/22] Port queries to Tracker3
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-documents/wip/carlosg/tracker3: 20/22] Port queries to Tracker3
- Date: Fri, 22 Oct 2021 10:11:53 +0000 (UTC)
commit 3296833675ff48f7c578ac766aeac346e7911d68
Author: Carlos Garnacho <carlosg gnome org>
Date: Sun Jan 17 17:03:14 2021 +0100
Port queries to Tracker3
Use new Tracker.SparqlConnection constructors, and rework the queries
so that it:
1) Observes the data layout in use in Tracker Miners 3.x
2) Uses a private database for the data considered writeable:
- collections
- titles
3) Queries g-o-m miners specifically, alongside local data
All queries happen on the local connection, optionally including data
from tracker-miner-fs and g-o-m miners via SERVICE{} clauses, this is
just not the case for collection queries, since collections are stored
in the private documents database.
meson.build | 4 +-
src/application.js | 8 ++-
src/documents.js | 2 +-
src/main.js | 3 +-
src/query.js | 136 ++++++++++++++++++++++++++++++++++++++---------
src/search.js | 4 +-
src/trackerController.js | 4 +-
src/trackerUtils.js | 2 +-
8 files changed, 127 insertions(+), 36 deletions(-)
---
diff --git a/meson.build b/meson.build
index 7a6d1ad0..1f63b310 100644
--- a/meson.build
+++ b/meson.build
@@ -54,7 +54,6 @@ endforeach
add_project_arguments('-DHAVE_CONFIG_H', language: 'c')
evince_req_version = '>= 3.13.3'
-tracker_req_version = '>= 0.17.3'
gjs_dep = dependency('gjs-1.0', version: '>= 1.48.0')
gjs_console = gjs_dep.get_pkgconfig_variable('gjs_console')
@@ -68,8 +67,7 @@ documents_deps = [
dependency('gobject-introspection-1.0', version: '>= 1.31.6'),
dependency('gtk+-3.0', version: '>= 3.22.15'),
dependency('libsoup-2.4', version: '>= 2.41.3'),
- dependency('tracker-control-2.0', version: tracker_req_version),
- dependency('tracker-sparql-2.0', version: tracker_req_version),
+ dependency('tracker-sparql-3.0'),
dependency('webkit2gtk-4.0', version: '>= 2.6.0'),
cc.find_library('m')
]
diff --git a/src/application.js b/src/application.js
index d1a1d454..73cd2da1 100644
--- a/src/application.js
+++ b/src/application.js
@@ -337,9 +337,13 @@ var Application = GObject.registerClass({
// connect to tracker
try {
- connection = Tracker.SparqlConnection.get(null);
+ let cacheDir = GLib.build_filenamev([GLib.get_user_cache_dir(), 'org.gnome.Documents', 'db']);
+ let nepomuk = Tracker.sparql_get_ontology_nepomuk();
+ connection = Tracker.SparqlConnection.new(Tracker.SparqlConnectionFlags.NONE,
+ Gio.File.new_for_path(cacheDir),
+ nepomuk, null);
} catch (e) {
- logError(e, 'Unable to connect to the tracker database');
+ logError(e, 'Unable to set up the tracker database');
return;
}
diff --git a/src/documents.js b/src/documents.js
index 752b5714..d2ad55f9 100644
--- a/src/documents.js
+++ b/src/documents.js
@@ -776,7 +776,7 @@ const DocCommon = class DocCommon {
let retval = '';
if (this.collection)
- retval = '{ ?urn nie:isPartOf <' + this.id + '> }';
+ retval = '{ ?urn nie:isLogicalPartOf <' + this.id + '> }';
return retval;
}
diff --git a/src/main.js b/src/main.js
index b4afb261..9094f889 100644
--- a/src/main.js
+++ b/src/main.js
@@ -33,8 +33,7 @@ pkg.require({ 'EvinceDocument': '3.0',
'Goa': '1.0',
'Gtk': '3.0',
'GObject': '2.0',
- 'Tracker': '2.0',
- 'TrackerControl': '2.0',
+ 'Tracker': '3.0',
'WebKit2': '4.0' });
const Application = imports.application;
diff --git a/src/query.js b/src/query.js
index 6ab1a462..4f5142ea 100644
--- a/src/query.js
+++ b/src/query.js
@@ -90,9 +90,6 @@ var QueryBuilder = class QueryBuilder {
part += this._buildOptional();
if ((flags & QueryFlags.UNFILTERED) == 0) {
- if (global)
- part += this._context.documentManager.getWhere();
-
part += this._buildFilterString(currentType, flags, ftsQuery.length > 0);
}
@@ -141,6 +138,18 @@ var QueryBuilder = class QueryBuilder {
}
_buildQueryInternal(global, flags, offsetController, sortBy) {
+ let selectClauses =
+ ' (COALESCE (nie:url(?urn), nie:isStoredAs(?urn)) AS ?uri) ' +
+ ' (COALESCE (nfo:fileName(?urn), tracker:string-from-filename(nie:isStoredAs(?urn))) AS
?filename) ' +
+ ' (nie:mimeType(?urn) AS ?mimetype) ' +
+ ' (nie:title(?urn) AS ?title) ' +
+ ' (tracker:coalesce(nco:fullname(?creator), nco:fullname(?publisher), \'\') AS ?author) ' +
+ ' (nie:contentLastModified(?urn) AS ?mtime) ' +
+ ' (nao:identifier(?urn) AS ?identifier) ' +
+ ' (rdf:type(?urn) AS ?type) ' +
+ ' (nie:dataSource(?urn) AS ?datasource ) ' +
+ ' (( EXISTS { ?urn nco:contributor ?contributor FILTER ( ?contributor != ?creator ) } ) AS
?shared) ' +
+ ' (nie:contentCreated(?urn) AS ?created) ';
let whereSparql = this._buildWhere(global, flags);
let tailSparql = '';
@@ -175,19 +184,61 @@ var QueryBuilder = class QueryBuilder {
}
let sparql =
- 'SELECT DISTINCT ?urn ' + // urn
- 'nie:url(?urn) ' + // uri
- 'nfo:fileName(?urn) AS ?filename ' + // filename
- 'nie:mimeType(?urn)' + // mimetype
- 'nie:title(?urn) AS ?title ' + // title
- 'tracker:coalesce(nco:fullname(?creator), nco:fullname(?publisher), \'\') AS ?author ' + //
author
- 'tracker:coalesce(nfo:fileLastModified(?urn), nie:contentLastModified(?urn)) AS ?mtime ' + //
mtime
- 'nao:identifier(?urn) ' + // identifier
- 'rdf:type(?urn) ' + // type
- 'nie:dataSource(?urn) ' + // resource URN
- '( EXISTS { ?urn nco:contributor ?contributor FILTER ( ?contributor != ?creator ) } ) ' + //
shared
- 'tracker:coalesce(nfo:fileCreated(?urn), nie:contentCreated(?urn)) ' + // date created
- whereSparql + tailSparql;
+ 'SELECT ?urn ' +
+ ' ?uri ' +
+ ' ?filename ' +
+ ' ?mimetype ' +
+ ' COALESCE (?localTitle, ?title, ?filename) AS ?t ' +
+ ' ?author ' +
+ ' ?mtime ' +
+ ' ?identifier ' +
+ ' ?type ' +
+ ' ?datasource ' +
+ ' ?shared ' +
+ ' ?created ' +
+ 'WHERE { ';
+
+ // Collections queries are local
+ if (flags & QueryFlags.COLLECTIONS) {
+ sparql +=
+ 'SELECT DISTINCT ?urn ' +
+ selectClauses +
+ whereSparql;
+ } else {
+ let services = ['org.freedesktop.Tracker3.Miner.Files'];
+ let serviceQueries = [];
+
+ if (this._context.sourceManager.hasProviderType('google'))
+ services.push('org.gnome.OnlineMiners.GData');
+ if (this._context.sourceManager.hasProviderType('owncloud'))
+ services.push('org.gnome.OnlineMiners.Owncloud');
+ if (this._context.sourceManager.hasProviderType('windows_live'))
+ services.push('org.gnome.OnlineMiners.Zpj');
+
+ services.forEach((service) => {
+ let serviceQuery =
+ '{' +
+ ' SERVICE SILENT <dbus:' + service + '> {' +
+ ' GRAPH tracker:Documents { ' +
+ ' SELECT DISTINCT ?urn ' +
+ selectClauses +
+ whereSparql +
+ ' }' +
+ ' }' +
+ '}';
+
+ serviceQueries.push(serviceQuery);
+ });
+
+ sparql += serviceQueries.join(' UNION ');
+ sparql += 'OPTIONAL { ?urn nie:title ?localTitle } . ';
+
+ if (global && (flags & QueryFlags.UNFILTERED) == 0)
+ sparql += this._context.documentManager.getWhere();
+ }
+
+ sparql += '}';
+ sparql += tailSparql;
return sparql;
}
@@ -204,8 +255,39 @@ var QueryBuilder = class QueryBuilder {
}
buildCountQuery(flags) {
- let sparql = 'SELECT DISTINCT COUNT(?urn) ' +
- this._buildWhere(true, flags);
+ let sparql;
+ if (flags & QueryFlags.COLLECTIONS) {
+ sparql = 'SELECT DISTINCT COUNT(?urn) AS ?c ' +
+ this._buildWhere(true, flags);
+ } else {
+ let services = ['org.freedesktop.Tracker3.Miner.Files'];
+ let countQueries = [];
+
+ if (this._context.sourceManager.hasProviderType('google'))
+ services.push('org.gnome.OnlineMiners.GData');
+ if (this._context.sourceManager.hasProviderType('owncloud'))
+ services.push('org.gnome.OnlineMiners.Owncloud');
+ if (this._context.sourceManager.hasProviderType('windows_live'))
+ services.push('org.gnome.OnlineMiners.Zpj');
+
+ sparql = 'SELECT SUM(?c) {';
+
+ services.forEach((service) => {
+ let countQuery =
+ '{ ' +
+ ' SERVICE SILENT <dbus:' + service + '> { ' +
+ ' GRAPH tracker:Documents { ' +
+ ' SELECT DISTINCT COUNT(?urn) AS ?c ' +
+ this._buildWhere(true, flags) +
+ ' }' +
+ ' }' +
+ '}';
+ countQueries.push(countQuery);
+ });
+
+ sparql += countQueries.join(' UNION ');
+ sparql += '}';
+ }
return this._createQuery(sparql);
}
@@ -215,8 +297,8 @@ var QueryBuilder = class QueryBuilder {
let sparql =
('SELECT ' +
'?urn ' +
- 'tracker:coalesce(nfo:fileLastModified(?urn), nie:contentLastModified(?urn)) AS ?mtime ' +
- 'WHERE { ?urn nie:isPartOf ?collUrn } ' +
+ 'nie:contentLastModified(?urn) AS ?mtime ' +
+ 'WHERE { ?urn nie:isLogicalPartOf ?collUrn } ' +
'ORDER BY DESC (?mtime)' +
'LIMIT 4').replace(/\?collUrn/, '<' + resource + '>');
@@ -228,7 +310,7 @@ var QueryBuilder = class QueryBuilder {
let sparql =
('SELECT ' +
'?urn ' +
- 'WHERE { ?urn a nfo:DataContainer . ?docUrn nie:isPartOf ?urn }'
+ 'WHERE { ?urn a nfo:DataContainer . ?docUrn nie:isLogicalPartOf ?urn }'
).replace(/\?docUrn/, '<' + resource + '>');
return this._createQuery(sparql);
@@ -236,15 +318,21 @@ var QueryBuilder = class QueryBuilder {
// adds or removes the given item to the given collection
buildSetCollectionQuery(itemUrn, collectionUrn, setting) {
- let sparql = ('%s { <%s> nie:isPartOf <%s> }'
- ).format((setting ? 'INSERT' : 'DELETE'), itemUrn, collectionUrn);
+ let sparql;
+ if (setting) {
+ sparql = ('INSERT DATA { <%s> a nie:InformationElement; nie:isLogicalPartOf <%s> }'
+ ).format(itemUrn, collectionUrn);
+ } else {
+ sparql = ('DELETE DATA { <%s> nie:isLogicalPartOf <%s> }'
+ ).format(itemUrn, collectionUrn);
+ }
return this._createQuery(sparql);
}
// bumps the mtime to current time for the given resource
buildUpdateMtimeQuery(resource) {
let time = GdPrivate.iso8601_from_timestamp(GLib.get_real_time() / GLib.USEC_PER_SEC);
- let sparql = ('INSERT OR REPLACE { <%s> nie:contentLastModified \"%s\" }'
+ let sparql = ('INSERT OR REPLACE { <%s> a nie:InformationElement; nie:contentLastModified \"%s\" }'
).format(resource, time);
return this._createQuery(sparql);
diff --git a/src/search.js b/src/search.js
index 738ca336..557c7a0a 100644
--- a/src/search.js
+++ b/src/search.js
@@ -19,6 +19,8 @@
*
*/
+imports.gi.versions.Tracker = '3.0';
+
const Application = imports.application;
const Documents = imports.documents;
const Manager = imports.manager;
@@ -328,7 +330,7 @@ const Source = class Source {
let filters = [];
locations.forEach((location) => {
- filters.push('(fn:contains (nie:url(?urn), "%s"))'.format(location.get_uri()));
+ filters.push('(fn:contains (nie:isStoredAs(?urn), "%s"))'.format(location.get_uri()));
});
filters.push('(fn:starts-with (nao:identifier(?urn), "gd:collection:local:"))');
diff --git a/src/trackerController.js b/src/trackerController.js
index 23e1c137..169ddcb5 100644
--- a/src/trackerController.js
+++ b/src/trackerController.js
@@ -86,10 +86,10 @@ var TrackerConnectionQueue = class TrackerConnectionQueue {
Application.connection.query_async(params.query, params.cancellable,
this._queueCollector.bind(this, params));
else if (params.queryType == QueryType.UPDATE)
- Application.connection.update_async(params.query, GLib.PRIORITY_DEFAULT, params.cancellable,
+ Application.connection.update_async(params.query, params.cancellable,
this._queueCollector.bind(this, params));
else if (params.queryType == QueryType.UPDATE_BLANK)
- Application.connection.update_blank_async(params.query, GLib.PRIORITY_DEFAULT,
params.cancellable,
+ Application.connection.update_blank_async(params.query, params.cancellable,
this._queueCollector.bind(this, params));
}
diff --git a/src/trackerUtils.js b/src/trackerUtils.js
index 007568c1..1ed63f2e 100644
--- a/src/trackerUtils.js
+++ b/src/trackerUtils.js
@@ -22,7 +22,7 @@
const Application = imports.application;
function setEditedName(newTitle, docId, callback) {
- let sparql = ('INSERT OR REPLACE { <%s> nie:title \"%s\" }'.format(docId, newTitle));
+ let sparql = ('INSERT OR REPLACE { <%s> a nie:InformationElement ; nie:title \"%s\" }'.format(docId,
newTitle));
Application.connectionQueue.update(sparql, null,
function(object, res) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]