[gnome-books/wip/carlosg/tracker3: 9/15] Port queries to Tracker3
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-books/wip/carlosg/tracker3: 9/15] Port queries to Tracker3
- Date: Mon, 22 Feb 2021 12:26:01 +0000 (UTC)
commit 3e066e63742f88eab0f131faa6bc7e70fc78da3b
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
All queries happen on the local connection, optionally including data
from tracker-miner-fs via SERVICE{} clauses, this is just not the case
for collection queries, since collections are stored in the private
books database.
meson.build | 4 +-
src/application.js | 8 +++-
src/documents.js | 2 +-
src/main.js | 3 +-
src/query.js | 99 ++++++++++++++++++++++++++++++++++++------------
src/search.js | 8 ++--
src/trackerController.js | 4 +-
src/trackerUtils.js | 2 +-
8 files changed, 92 insertions(+), 38 deletions(-)
---
diff --git a/meson.build b/meson.build
index afd97aa4..f608bfc1 100644
--- a/meson.build
+++ b/meson.build
@@ -50,7 +50,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')
@@ -63,8 +62,7 @@ books_deps = [
dependency('gnome-desktop-3.0'),
dependency('gobject-introspection-1.0', version: '>= 1.31.6'),
dependency('gtk+-3.0', version: '>= 3.22.15'),
- 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 a6ac6f0f..c3ebf933 100644
--- a/src/application.js
+++ b/src/application.js
@@ -175,9 +175,13 @@ var Application = new Lang.Class({
// connect to tracker
try {
- connection = Tracker.SparqlConnection.get(null);
+ let cacheDir = GLib.build_filenamev([GLib.get_user_cache_dir(), 'org.gnome.Books', '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 b6aea652..a2f15c6b 100644
--- a/src/documents.js
+++ b/src/documents.js
@@ -803,7 +803,7 @@ const DocCommon = new Lang.Class({
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 57f62019..d6624940 100644
--- a/src/main.js
+++ b/src/main.js
@@ -33,8 +33,7 @@ pkg.require({ 'EvinceDocument': '3.0',
'GLib': '2.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 ce7928cd..fa7c5ca1 100644
--- a/src/query.js
+++ b/src/query.js
@@ -94,9 +94,6 @@ var QueryBuilder = new Lang.Class({
part += this._buildOptional();
if ((flags & QueryFlags.UNFILTERED) == 0) {
- if (global)
- part += this._context.documentManager.getWhere();
-
part += this._buildFilterString(currentType, flags, ftsQuery.length > 0);
}
@@ -139,12 +136,25 @@ var QueryBuilder = new Lang.Class({
// put all the clauses in an UNION
whereSparql += whereParts.join(' UNION ');
+
whereSparql += ' }';
return whereSparql;
},
_buildQueryInternal: function(global, flags, offsetController, sortBy) {
+ let selectClauses =
+ ' (nie:isStoredAs(?urn) AS ?uri) ' +
+ ' (nfo:fileName(?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 = '';
@@ -179,19 +189,44 @@ var QueryBuilder = new Lang.Class({
}
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) ' +
+ ' ?author ' +
+ ' ?mtime ' +
+ ' ?identifier ' +
+ ' ?type ' +
+ ' ?datasource ' +
+ ' ?shared ' +
+ ' ?created ' +
+ 'WHERE { ';
+
+ // Collections queries are local
+ if (flags & QueryFlags.COLLECTIONS) {
+ sparql +=
+ 'SELECT DISTINCT ?urn ' +
+ selectClauses +
+ whereSparql +
+ tailSparql;
+ } else {
+ sparql +=
+ 'SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> {' +
+ ' GRAPH tracker:Documents { ' +
+ ' SELECT DISTINCT ?urn ' +
+ selectClauses +
+ whereSparql +
+ tailSparql +
+ ' }' +
+ '}' +
+ 'OPTIONAL { ?urn nie:title ?localTitle } . ';
+
+ if (global && (flags & QueryFlags.UNFILTERED) == 0)
+ sparql += this._context.documentManager.getWhere();
+ }
+
+ sparql += '}';
return sparql;
},
@@ -208,8 +243,18 @@ var QueryBuilder = new Lang.Class({
},
buildCountQuery: function(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 {
+ sparql = 'SELECT ?c {' +
+ ' SERVICE <dbus:org.freedesktop.Tracker3.Miner.Files> { ' +
+ ' SELECT DISTINCT COUNT(?urn) AS ?c ' +
+ this._buildWhere(true, flags) +
+ ' }' +
+ '}';
+ }
return this._createQuery(sparql);
},
@@ -219,8 +264,8 @@ var QueryBuilder = new Lang.Class({
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 + '>');
@@ -232,7 +277,7 @@ var QueryBuilder = new Lang.Class({
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);
@@ -240,15 +285,21 @@ var QueryBuilder = new Lang.Class({
// adds or removes the given item to the given collection
buildSetCollectionQuery: function(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: function(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 1a25f3ed..0bcc6d2c 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;
@@ -126,11 +128,11 @@ const SearchTypeManager = new Lang.Class({
this.addItem(new SearchType({ id: SearchTypeStock.EBOOKS,
name: _("e-Books"),
filter: '(nie:mimeType(?urn) IN (\"application/epub+zip\",
\"application/x-mobipocket-ebook\", \"application/vnd.amazon.mobi8-ebook\",
\"application/x-fictionbook+xml\", \"application/x-zip-compressed-fb2\", \"image/vnd.djvu+multipage\"))',
- where: '?urn rdf:type nfo:FileDataObject .' }));
+ where: '?urn rdf:type nfo:EBook .' }));
this.addItem(new SearchType({ id: SearchTypeStock.COMICS,
name: _("Comics"),
filter: '(nie:mimeType(?urn) IN (\"application/x-cbr\",
\"application/vnd.comicbook-rar\", \"application/x-cbz\", \"application/vnd.comicbook+zip\",
\"application/x-cbt\", \"application/x-cb7\"))',
- where: '?urn rdf:type nfo:FileDataObject .' }));
+ where: '?urn rdf:type nfo:EBook .' }));
this.setActiveItemById(SearchTypeStock.ALL);
@@ -322,7 +324,7 @@ const Source = new Lang.Class({
let filters = [];
locations.forEach(Lang.bind(this,
function(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), "gb:collection:local:"))');
diff --git a/src/trackerController.js b/src/trackerController.js
index e45f3a7f..17507e03 100644
--- a/src/trackerController.js
+++ b/src/trackerController.js
@@ -89,10 +89,10 @@ var TrackerConnectionQueue = new Lang.Class({
Application.connection.query_async(params.query, params.cancellable,
Lang.bind(this, this._queueCollector, 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,
Lang.bind(this, this._queueCollector, 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,
Lang.bind(this, this._queueCollector, params));
},
diff --git a/src/trackerUtils.js b/src/trackerUtils.js
index a1653fed..c98a3345 100644
--- a/src/trackerUtils.js
+++ b/src/trackerUtils.js
@@ -24,7 +24,7 @@ const Lang = imports.lang;
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]