Chris@439
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@439
|
2
|
Chris@439
|
3 /*
|
Chris@439
|
4 Sonic Visualiser
|
Chris@439
|
5 An audio file viewer and annotation editor.
|
Chris@439
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@439
|
7 This file copyright 2008 QMUL.
|
Chris@439
|
8
|
Chris@439
|
9 This program is free software; you can redistribute it and/or
|
Chris@439
|
10 modify it under the terms of the GNU General Public License as
|
Chris@439
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@439
|
12 License, or (at your option) any later version. See the file
|
Chris@439
|
13 COPYING included with this distribution for more information.
|
Chris@439
|
14 */
|
Chris@439
|
15
|
Chris@439
|
16 #include "SimpleSPARQLQuery.h"
|
Chris@439
|
17 #include "base/ProgressReporter.h"
|
Chris@480
|
18 #include "base/Profiler.h"
|
Chris@480
|
19
|
Chris@480
|
20 #include <QMutex>
|
Chris@480
|
21 #include <QMutexLocker>
|
Chris@481
|
22 #include <QRegExp>
|
Chris@480
|
23
|
Chris@480
|
24 #include <set>
|
Chris@439
|
25
|
Chris@440
|
26 #ifdef USE_NEW_RASQAL_API
|
Chris@440
|
27 #include <rasqal/rasqal.h>
|
Chris@440
|
28 #else
|
Chris@439
|
29 #include <rasqal.h>
|
Chris@440
|
30 #endif
|
Chris@439
|
31
|
Chris@480
|
32 #ifdef HAVE_REDLAND
|
Chris@480
|
33 #include <redland.h>
|
Chris@480
|
34 #endif
|
Chris@480
|
35
|
Chris@461
|
36 //#define DEBUG_SIMPLE_SPARQL_QUERY 1
|
Chris@461
|
37
|
Chris@439
|
38 #include <iostream>
|
Chris@439
|
39
|
Chris@439
|
40 using std::cerr;
|
Chris@439
|
41 using std::endl;
|
Chris@439
|
42
|
Chris@440
|
43 #ifdef USE_NEW_RASQAL_API
|
Chris@440
|
44 class WrasqalWorldWrapper // wrong but wromantic, etc
|
Chris@440
|
45 {
|
Chris@440
|
46 public:
|
Chris@481
|
47 WrasqalWorldWrapper() :
|
Chris@481
|
48 m_world(0)
|
Chris@481
|
49 {
|
Chris@481
|
50 m_world = rasqal_new_world();
|
Chris@481
|
51 if (!m_world) {
|
Chris@481
|
52 cerr << "SimpleSPARQLQuery: ERROR: Failed to create RASQAL world!" << endl;
|
Chris@481
|
53 return;
|
Chris@481
|
54 }
|
Chris@481
|
55 /*!!! This appears to be new for 0.9.17?
|
Chris@481
|
56 if (rasqal_world_open(m_world)) {
|
Chris@481
|
57 cerr << "SimpleSPARQLQuery: ERROR: Failed to open RASQAL world!" << endl;
|
Chris@481
|
58 return;
|
Chris@481
|
59 }
|
Chris@481
|
60 */
|
Chris@481
|
61 }
|
Chris@481
|
62 ~WrasqalWorldWrapper()
|
Chris@481
|
63 {
|
Chris@481
|
64 rasqal_free_world(m_world);
|
Chris@481
|
65 }
|
Chris@440
|
66
|
Chris@480
|
67 rasqal_world *getWorld() { return m_world; }
|
Chris@480
|
68 const rasqal_world *getWorld() const { return m_world; }
|
Chris@440
|
69
|
Chris@440
|
70 private:
|
Chris@440
|
71 rasqal_world *m_world;
|
Chris@440
|
72 };
|
Chris@440
|
73 #endif
|
Chris@440
|
74
|
Chris@480
|
75 #ifdef HAVE_REDLAND
|
Chris@480
|
76 class WredlandWorldWrapper
|
Chris@480
|
77 {
|
Chris@480
|
78 public:
|
Chris@480
|
79 WredlandWorldWrapper() :
|
Chris@480
|
80 m_world(0), m_storage(0), m_model(0)
|
Chris@480
|
81 {
|
Chris@480
|
82 m_world = librdf_new_world();
|
Chris@481
|
83 if (!m_world) {
|
Chris@481
|
84 cerr << "SimpleSPARQLQuery: ERROR: Failed to create LIBRDF world!" << endl;
|
Chris@481
|
85 return;
|
Chris@481
|
86 }
|
Chris@480
|
87 librdf_world_open(m_world);
|
Chris@481
|
88 m_storage = librdf_new_storage(m_world, "trees", NULL, NULL);
|
Chris@480
|
89 if (!m_storage) {
|
Chris@481
|
90 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland trees datastore, falling back to memory store" << std::endl;
|
Chris@480
|
91 m_storage = librdf_new_storage(m_world, NULL, NULL, NULL);
|
Chris@480
|
92 if (!m_storage) {
|
Chris@480
|
93 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland memory datastore" << std::endl;
|
Chris@480
|
94 return;
|
Chris@480
|
95 }
|
Chris@480
|
96 }
|
Chris@480
|
97 m_model = librdf_new_model(m_world, m_storage, NULL);
|
Chris@480
|
98 if (!m_model) {
|
Chris@480
|
99 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland data model" << std::endl;
|
Chris@480
|
100 return;
|
Chris@480
|
101 }
|
Chris@480
|
102 }
|
Chris@480
|
103
|
Chris@480
|
104 ~WredlandWorldWrapper()
|
Chris@480
|
105 {
|
Chris@480
|
106 while (!m_parsedUris.empty()) {
|
Chris@480
|
107 librdf_free_uri(m_parsedUris.begin()->second);
|
Chris@480
|
108 m_parsedUris.erase(m_parsedUris.begin());
|
Chris@480
|
109 }
|
Chris@480
|
110 if (m_model) librdf_free_model(m_model);
|
Chris@480
|
111 if (m_storage) librdf_free_storage(m_storage);
|
Chris@480
|
112 if (m_world) librdf_free_world(m_world);
|
Chris@480
|
113 }
|
Chris@480
|
114
|
Chris@480
|
115 bool isOK() const { return (m_model != 0); }
|
Chris@480
|
116
|
Chris@480
|
117 librdf_uri *getUri(QString uriString, QString &errorString)
|
Chris@480
|
118 {
|
Chris@480
|
119 QMutexLocker locker(&m_mutex);
|
Chris@480
|
120
|
Chris@480
|
121 if (m_parsedUris.find(uriString) != m_parsedUris.end()) {
|
Chris@480
|
122 return m_parsedUris[uriString];
|
Chris@480
|
123 }
|
Chris@480
|
124
|
Chris@480
|
125 librdf_uri *uri = librdf_new_uri
|
Chris@480
|
126 (m_world, (const unsigned char *)uriString.toUtf8().data());
|
Chris@480
|
127 if (!uri) {
|
Chris@480
|
128 errorString = "Failed to construct librdf_uri!";
|
Chris@480
|
129 return 0;
|
Chris@480
|
130 }
|
Chris@480
|
131
|
Chris@480
|
132 librdf_parser *parser = librdf_new_parser(m_world, "guess", NULL, NULL);
|
Chris@480
|
133 if (!parser) {
|
Chris@480
|
134 errorString = "Failed to initialise Redland parser";
|
Chris@480
|
135 return 0;
|
Chris@480
|
136 }
|
Chris@480
|
137
|
Chris@480
|
138 std::cerr << "About to parse \"" << uriString.toStdString() << "\"" << std::endl;
|
Chris@480
|
139
|
Chris@480
|
140 Profiler p("SimpleSPARQLQuery: Parse URI into LIBRDF model");
|
Chris@480
|
141
|
Chris@480
|
142 if (librdf_parser_parse_into_model(parser, uri, NULL, m_model)) {
|
Chris@480
|
143
|
Chris@480
|
144 errorString = QString("Failed to parse RDF from URI \"%1\"")
|
Chris@480
|
145 .arg(uriString);
|
Chris@480
|
146 librdf_free_parser(parser);
|
Chris@480
|
147 librdf_free_uri(uri);
|
Chris@480
|
148 return 0;
|
Chris@480
|
149
|
Chris@480
|
150 } else {
|
Chris@480
|
151
|
Chris@480
|
152 librdf_free_parser(parser);
|
Chris@480
|
153 m_parsedUris[uriString] = uri;
|
Chris@480
|
154 return uri;
|
Chris@480
|
155 }
|
Chris@480
|
156 }
|
Chris@480
|
157
|
Chris@480
|
158 librdf_world *getWorld() { return m_world; }
|
Chris@480
|
159 const librdf_world *getWorld() const { return m_world; }
|
Chris@480
|
160
|
Chris@480
|
161 librdf_model *getModel() { return m_model; }
|
Chris@480
|
162 const librdf_model *getModel() const { return m_model; }
|
Chris@480
|
163
|
Chris@480
|
164 private:
|
Chris@480
|
165 librdf_world *m_world;
|
Chris@480
|
166 librdf_storage *m_storage;
|
Chris@480
|
167 librdf_model *m_model;
|
Chris@480
|
168
|
Chris@480
|
169 QMutex m_mutex;
|
Chris@480
|
170 std::map<QString, librdf_uri *> m_parsedUris;
|
Chris@480
|
171 };
|
Chris@480
|
172 #endif
|
Chris@480
|
173
|
Chris@439
|
174 class SimpleSPARQLQuery::Impl
|
Chris@439
|
175 {
|
Chris@439
|
176 public:
|
Chris@480
|
177 Impl(QString fromUri, QString query);
|
Chris@439
|
178 ~Impl();
|
Chris@439
|
179
|
Chris@439
|
180 void setProgressReporter(ProgressReporter *reporter) { m_reporter = reporter; }
|
Chris@439
|
181 bool wasCancelled() const { return m_cancelled; }
|
Chris@439
|
182
|
Chris@439
|
183 ResultList execute();
|
Chris@439
|
184
|
Chris@439
|
185 bool isOK() const;
|
Chris@439
|
186 QString getErrorString() const;
|
Chris@439
|
187
|
Chris@481
|
188 static void setBackEnd(SimpleSPARQLQuery::BackEndPreference p) {
|
Chris@480
|
189 m_preference = p;
|
Chris@480
|
190 }
|
Chris@480
|
191
|
Chris@439
|
192 protected:
|
Chris@439
|
193 static void errorHandler(void *, raptor_locator *, const char *);
|
Chris@439
|
194
|
Chris@480
|
195 static QMutex m_mutex;
|
Chris@480
|
196
|
Chris@440
|
197 #ifdef USE_NEW_RASQAL_API
|
Chris@480
|
198 static WrasqalWorldWrapper *m_rasqal;
|
Chris@440
|
199 #else
|
Chris@480
|
200 static bool m_rasqalInitialised;
|
Chris@440
|
201 #endif
|
Chris@480
|
202
|
Chris@480
|
203 #ifdef HAVE_REDLAND
|
Chris@480
|
204 static WredlandWorldWrapper *m_redland;
|
Chris@480
|
205 #endif
|
Chris@480
|
206
|
Chris@481
|
207 static SimpleSPARQLQuery::BackEndPreference m_preference;
|
Chris@480
|
208
|
Chris@480
|
209 ResultList executeDirectParser();
|
Chris@480
|
210 ResultList executeDatastore();
|
Chris@480
|
211
|
Chris@480
|
212 QString m_fromUri;
|
Chris@439
|
213 QString m_query;
|
Chris@439
|
214 QString m_errorString;
|
Chris@439
|
215 ProgressReporter *m_reporter;
|
Chris@439
|
216 bool m_cancelled;
|
Chris@439
|
217 };
|
Chris@439
|
218
|
Chris@440
|
219 #ifdef USE_NEW_RASQAL_API
|
Chris@480
|
220 WrasqalWorldWrapper *SimpleSPARQLQuery::Impl::m_rasqal = 0;
|
Chris@440
|
221 #else
|
Chris@480
|
222 bool SimpleSPARQLQuery::Impl::m_rasqalInitialised = false;
|
Chris@440
|
223 #endif
|
Chris@440
|
224
|
Chris@480
|
225 #ifdef HAVE_REDLAND
|
Chris@480
|
226 WredlandWorldWrapper *SimpleSPARQLQuery::Impl::m_redland = 0;
|
Chris@480
|
227 #endif
|
Chris@480
|
228
|
Chris@480
|
229 QMutex SimpleSPARQLQuery::Impl::m_mutex;
|
Chris@480
|
230
|
Chris@481
|
231 SimpleSPARQLQuery::BackEndPreference
|
Chris@481
|
232 SimpleSPARQLQuery::Impl::m_preference = SimpleSPARQLQuery::AutoSelectBackEnd;
|
Chris@480
|
233
|
Chris@480
|
234 SimpleSPARQLQuery::SimpleSPARQLQuery(QString fromUri, QString query) :
|
Chris@480
|
235 m_impl(new Impl(fromUri, query))
|
Chris@480
|
236 {
|
Chris@480
|
237 }
|
Chris@439
|
238
|
Chris@439
|
239 SimpleSPARQLQuery::~SimpleSPARQLQuery()
|
Chris@439
|
240 {
|
Chris@439
|
241 delete m_impl;
|
Chris@439
|
242 }
|
Chris@439
|
243
|
Chris@439
|
244 void
|
Chris@439
|
245 SimpleSPARQLQuery::setProgressReporter(ProgressReporter *reporter)
|
Chris@439
|
246 {
|
Chris@439
|
247 m_impl->setProgressReporter(reporter);
|
Chris@439
|
248 }
|
Chris@439
|
249
|
Chris@439
|
250 bool
|
Chris@439
|
251 SimpleSPARQLQuery::wasCancelled() const
|
Chris@439
|
252 {
|
Chris@439
|
253 return m_impl->wasCancelled();
|
Chris@439
|
254 }
|
Chris@439
|
255
|
Chris@439
|
256 SimpleSPARQLQuery::ResultList
|
Chris@439
|
257 SimpleSPARQLQuery::execute()
|
Chris@439
|
258 {
|
Chris@439
|
259 return m_impl->execute();
|
Chris@439
|
260 }
|
Chris@439
|
261
|
Chris@439
|
262 bool
|
Chris@439
|
263 SimpleSPARQLQuery::isOK() const
|
Chris@439
|
264 {
|
Chris@439
|
265 return m_impl->isOK();
|
Chris@439
|
266 }
|
Chris@439
|
267
|
Chris@439
|
268 QString
|
Chris@439
|
269 SimpleSPARQLQuery::getErrorString() const
|
Chris@439
|
270 {
|
Chris@439
|
271 return m_impl->getErrorString();
|
Chris@439
|
272 }
|
Chris@439
|
273
|
Chris@480
|
274 void
|
Chris@481
|
275 SimpleSPARQLQuery::setBackEnd(BackEndPreference p)
|
Chris@480
|
276 {
|
Chris@481
|
277 SimpleSPARQLQuery::Impl::setBackEnd(p);
|
Chris@480
|
278 }
|
Chris@480
|
279
|
Chris@480
|
280 SimpleSPARQLQuery::Impl::Impl(QString fromUri, QString query) :
|
Chris@480
|
281 m_fromUri(fromUri),
|
Chris@439
|
282 m_query(query),
|
Chris@439
|
283 m_reporter(0),
|
Chris@439
|
284 m_cancelled(false)
|
Chris@439
|
285 {
|
Chris@461
|
286 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
|
Chris@461
|
287 std::cerr << "SimpleSPARQLQuery::Impl: Query is: \"" << query.toStdString() << "\"" << std::endl;
|
Chris@461
|
288 #endif
|
Chris@439
|
289 }
|
Chris@439
|
290
|
Chris@439
|
291 SimpleSPARQLQuery::Impl::~Impl()
|
Chris@439
|
292 {
|
Chris@439
|
293 }
|
Chris@439
|
294
|
Chris@439
|
295 bool
|
Chris@439
|
296 SimpleSPARQLQuery::Impl::isOK() const
|
Chris@439
|
297 {
|
Chris@439
|
298 return (m_errorString == "");
|
Chris@439
|
299 }
|
Chris@439
|
300
|
Chris@439
|
301 QString
|
Chris@439
|
302 SimpleSPARQLQuery::Impl::getErrorString() const
|
Chris@439
|
303 {
|
Chris@439
|
304 return m_errorString;
|
Chris@439
|
305 }
|
Chris@439
|
306
|
Chris@439
|
307 void
|
Chris@439
|
308 SimpleSPARQLQuery::Impl::errorHandler(void *data,
|
Chris@439
|
309 raptor_locator *locator,
|
Chris@439
|
310 const char *message)
|
Chris@439
|
311 {
|
Chris@439
|
312 SimpleSPARQLQuery::Impl *impl = (SimpleSPARQLQuery::Impl *)data;
|
Chris@439
|
313
|
Chris@481
|
314 char buffer[256];
|
Chris@481
|
315 raptor_format_locator(buffer, 255, locator);
|
Chris@481
|
316 QString loc(buffer);
|
Chris@481
|
317 if (loc != "") {
|
Chris@481
|
318 impl->m_errorString = QString("%1 - %2").arg(loc).arg(message);
|
Chris@481
|
319 } else {
|
Chris@481
|
320 impl->m_errorString = message;
|
Chris@481
|
321 }
|
Chris@439
|
322
|
Chris@439
|
323 cerr << "SimpleSPARQLQuery: ERROR: " << impl->m_errorString.toStdString() << endl;
|
Chris@439
|
324 }
|
Chris@439
|
325
|
Chris@439
|
326 SimpleSPARQLQuery::ResultList
|
Chris@439
|
327 SimpleSPARQLQuery::Impl::execute()
|
Chris@439
|
328 {
|
Chris@439
|
329 ResultList list;
|
Chris@439
|
330
|
Chris@481
|
331 BackEndPreference preference;
|
Chris@480
|
332
|
Chris@480
|
333 m_mutex.lock();
|
Chris@480
|
334
|
Chris@481
|
335 if (m_preference == AutoSelectBackEnd) {
|
Chris@481
|
336 #ifdef HAVE_REDLAND
|
Chris@481
|
337 // cerr << "librdf version: " << librdf_version_major << "." << librdf_version_minor << "." << librdf_version_release << endl;
|
Chris@481
|
338 if (librdf_version_major > 1 ||
|
Chris@481
|
339 (librdf_version_major == 1 &&
|
Chris@481
|
340 (librdf_version_minor > 0 ||
|
Chris@481
|
341 (librdf_version_minor == 0 &&
|
Chris@481
|
342 librdf_version_release > 7)))) {
|
Chris@481
|
343 cerr << "SimpleSPARQLQuery: Auto-selecting LIBRDF back-end for tree-based storage" << endl;
|
Chris@481
|
344 m_preference = DatastoreBackEnd;
|
Chris@481
|
345 }
|
Chris@481
|
346 #endif
|
Chris@481
|
347 if (m_preference == AutoSelectBackEnd) {
|
Chris@481
|
348 cerr << "SimpleSPARQLQuery: Auto-selecting RASQAL back-end" << endl;
|
Chris@481
|
349 m_preference = DirectParserBackEnd;
|
Chris@481
|
350 }
|
Chris@481
|
351 }
|
Chris@481
|
352
|
Chris@481
|
353 if (m_preference == DatastoreBackEnd) {
|
Chris@480
|
354 #ifdef HAVE_REDLAND
|
Chris@480
|
355 if (!m_redland) {
|
Chris@480
|
356 m_redland = new WredlandWorldWrapper();
|
Chris@480
|
357 if (!m_redland->isOK()) {
|
Chris@480
|
358 cerr << "WARNING: SimpleSPARQLQuery::execute: Failed to initialise Redland datastore, falling back to direct parser implementation" << endl;
|
Chris@480
|
359 delete m_redland;
|
Chris@481
|
360 m_preference = DirectParserBackEnd;
|
Chris@480
|
361 }
|
Chris@480
|
362 }
|
Chris@480
|
363 #else
|
Chris@480
|
364 cerr << "WARNING: SimpleSPARQLQuery::execute: Datastore implementation preference indicated, but no datastore compiled in; using direct parser" << endl;
|
Chris@481
|
365 m_preference = DirectParserBackEnd;
|
Chris@480
|
366 #endif
|
Chris@480
|
367 }
|
Chris@480
|
368
|
Chris@481
|
369 if (m_preference == DirectParserBackEnd) {
|
Chris@440
|
370 #ifdef USE_NEW_RASQAL_API
|
Chris@480
|
371 if (!m_rasqal) m_rasqal = new WrasqalWorldWrapper();
|
Chris@440
|
372 #else
|
Chris@480
|
373 if (!m_rasqalInitialised) {
|
Chris@480
|
374 rasqal_init();
|
Chris@480
|
375 m_rasqalInitialised = true;
|
Chris@480
|
376 }
|
Chris@480
|
377 #endif
|
Chris@440
|
378 }
|
Chris@480
|
379
|
Chris@480
|
380 preference = m_preference;
|
Chris@480
|
381 m_mutex.unlock();
|
Chris@480
|
382
|
Chris@481
|
383 if (preference == SimpleSPARQLQuery::DirectParserBackEnd) {
|
Chris@480
|
384 return executeDirectParser();
|
Chris@480
|
385 } else {
|
Chris@480
|
386 return executeDatastore();
|
Chris@480
|
387 }
|
Chris@480
|
388 }
|
Chris@480
|
389
|
Chris@480
|
390 SimpleSPARQLQuery::ResultList
|
Chris@480
|
391 SimpleSPARQLQuery::Impl::executeDirectParser()
|
Chris@480
|
392 {
|
Chris@480
|
393 ResultList list;
|
Chris@480
|
394
|
Chris@480
|
395 Profiler profiler("SimpleSPARQLQuery::executeDirectParser");
|
Chris@480
|
396
|
Chris@480
|
397 #ifdef USE_NEW_RASQAL_API
|
Chris@480
|
398 rasqal_query *query = rasqal_new_query(m_rasqal->getWorld(), "sparql", NULL);
|
Chris@480
|
399 #else
|
Chris@439
|
400 rasqal_query *query = rasqal_new_query("sparql", NULL);
|
Chris@440
|
401 #endif
|
Chris@439
|
402 if (!query) {
|
Chris@439
|
403 m_errorString = "Failed to construct query";
|
Chris@439
|
404 cerr << "SimpleSPARQLQuery: ERROR: " << m_errorString.toStdString() << endl;
|
Chris@439
|
405 return list;
|
Chris@439
|
406 }
|
Chris@439
|
407
|
Chris@439
|
408 rasqal_query_set_error_handler(query, this, errorHandler);
|
Chris@439
|
409 rasqal_query_set_fatal_error_handler(query, this, errorHandler);
|
Chris@439
|
410
|
Chris@480
|
411 {
|
Chris@480
|
412 Profiler p("SimpleSPARQLQuery: Prepare RASQAL query");
|
Chris@480
|
413
|
Chris@480
|
414 if (rasqal_query_prepare
|
Chris@480
|
415 (query, (const unsigned char *)m_query.toUtf8().data(), NULL)) {
|
Chris@480
|
416 cerr << "SimpleSPARQLQuery: Failed to prepare query" << endl;
|
Chris@480
|
417 rasqal_free_query(query);
|
Chris@480
|
418 return list;
|
Chris@480
|
419 }
|
Chris@439
|
420 }
|
Chris@439
|
421
|
Chris@480
|
422 rasqal_query_results *results;
|
Chris@480
|
423
|
Chris@480
|
424 {
|
Chris@480
|
425 Profiler p("SimpleSPARQLQuery: Execute RASQAL query");
|
Chris@480
|
426 results = rasqal_query_execute(query);
|
Chris@480
|
427 }
|
Chris@439
|
428
|
Chris@439
|
429 // cerr << "Query executed" << endl;
|
Chris@439
|
430
|
Chris@439
|
431 if (!results) {
|
Chris@439
|
432 cerr << "SimpleSPARQLQuery: RASQAL query failed" << endl;
|
Chris@439
|
433 rasqal_free_query(query);
|
Chris@439
|
434 return list;
|
Chris@439
|
435 }
|
Chris@439
|
436
|
Chris@439
|
437 if (!rasqal_query_results_is_bindings(results)) {
|
Chris@439
|
438 cerr << "SimpleSPARQLQuery: RASQAL query has wrong result type (not bindings)" << endl;
|
Chris@439
|
439 rasqal_free_query_results(results);
|
Chris@439
|
440 rasqal_free_query(query);
|
Chris@439
|
441 return list;
|
Chris@439
|
442 }
|
Chris@439
|
443
|
Chris@439
|
444 int resultCount = 0;
|
Chris@439
|
445 int resultTotal = rasqal_query_results_get_count(results); // probably wrong
|
Chris@439
|
446 m_cancelled = false;
|
Chris@439
|
447
|
Chris@439
|
448 while (!rasqal_query_results_finished(results)) {
|
Chris@439
|
449
|
Chris@439
|
450 int count = rasqal_query_results_get_bindings_count(results);
|
Chris@439
|
451
|
Chris@439
|
452 KeyValueMap resultmap;
|
Chris@439
|
453
|
Chris@439
|
454 for (int i = 0; i < count; ++i) {
|
Chris@439
|
455
|
Chris@439
|
456 const unsigned char *name =
|
Chris@439
|
457 rasqal_query_results_get_binding_name(results, i);
|
Chris@439
|
458
|
Chris@439
|
459 rasqal_literal *literal =
|
Chris@439
|
460 rasqal_query_results_get_binding_value(results, i);
|
Chris@439
|
461
|
Chris@439
|
462 QString key = (const char *)name;
|
Chris@439
|
463
|
Chris@439
|
464 if (!literal) {
|
Chris@439
|
465 resultmap[key] = Value();
|
Chris@439
|
466 continue;
|
Chris@439
|
467 }
|
Chris@439
|
468
|
Chris@439
|
469 ValueType type = LiteralValue;
|
Chris@439
|
470 if (literal->type == RASQAL_LITERAL_URI) type = URIValue;
|
Chris@439
|
471 else if (literal->type == RASQAL_LITERAL_BLANK) type = BlankValue;
|
Chris@439
|
472
|
Chris@439
|
473 QString text = (const char *)rasqal_literal_as_string(literal);
|
Chris@439
|
474
|
Chris@461
|
475 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
|
Chris@449
|
476 std::cerr << i << ". " << key.toStdString() << " -> " << text.toStdString() << " (type " << type << ")" << std::endl;
|
Chris@461
|
477 #endif
|
Chris@449
|
478
|
Chris@439
|
479 resultmap[key] = Value(type, text);
|
Chris@439
|
480 }
|
Chris@439
|
481
|
Chris@439
|
482 list.push_back(resultmap);
|
Chris@439
|
483
|
Chris@439
|
484 rasqal_query_results_next(results);
|
Chris@439
|
485
|
Chris@439
|
486 resultCount++;
|
Chris@439
|
487
|
Chris@439
|
488 if (m_reporter) {
|
Chris@439
|
489 if (resultCount >= resultTotal) {
|
Chris@439
|
490 if (m_reporter->isDefinite()) m_reporter->setDefinite(false);
|
Chris@439
|
491 m_reporter->setProgress(resultCount);
|
Chris@439
|
492 } else {
|
Chris@439
|
493 m_reporter->setProgress((resultCount * 100) / resultTotal);
|
Chris@439
|
494 }
|
Chris@439
|
495
|
Chris@439
|
496 if (m_reporter->wasCancelled()) {
|
Chris@439
|
497 m_cancelled = true;
|
Chris@439
|
498 break;
|
Chris@439
|
499 }
|
Chris@439
|
500 }
|
Chris@439
|
501 }
|
Chris@439
|
502
|
Chris@439
|
503 rasqal_free_query_results(results);
|
Chris@439
|
504 rasqal_free_query(query);
|
Chris@439
|
505
|
Chris@439
|
506 return list;
|
Chris@439
|
507 }
|
Chris@440
|
508
|
Chris@480
|
509 SimpleSPARQLQuery::ResultList
|
Chris@480
|
510 SimpleSPARQLQuery::Impl::executeDatastore()
|
Chris@480
|
511 {
|
Chris@480
|
512 ResultList list;
|
Chris@480
|
513 #ifndef HAVE_REDLAND
|
Chris@480
|
514 // This should have been caught by execute()
|
Chris@480
|
515 cerr << "SimpleSPARQLQuery: INTERNAL ERROR: Datastore not compiled in" << endl;
|
Chris@480
|
516 return list;
|
Chris@480
|
517 #else
|
Chris@480
|
518 Profiler profiler("SimpleSPARQLQuery::executeDatastore");
|
Chris@480
|
519
|
Chris@480
|
520 librdf_uri *uri = m_redland->getUri(m_fromUri, m_errorString);
|
Chris@480
|
521 if (!uri) return list;
|
Chris@480
|
522
|
Chris@481
|
523 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
|
Chris@480
|
524 std::cerr << "SimpleSPARQLQuery: Query is: \"" << m_query.toStdString() << "\"" << std::endl;
|
Chris@481
|
525 #endif
|
Chris@481
|
526 /*!!!
|
Chris@480
|
527 static std::map<QString, int> counter;
|
Chris@480
|
528 if (counter.find(m_query) == counter.end()) counter[m_query] = 1;
|
Chris@480
|
529 else ++counter[m_query];
|
Chris@480
|
530 std::cerr << "Counter for this query: " << counter[m_query] << std::endl;
|
Chris@481
|
531 std::cerr << "Base URI is: \"" << m_fromUri.toStdString() << "\"" << std::endl;
|
Chris@481
|
532 */
|
Chris@480
|
533
|
Chris@480
|
534 librdf_query *query;
|
Chris@480
|
535
|
Chris@480
|
536 {
|
Chris@480
|
537 Profiler p("SimpleSPARQLQuery: Prepare LIBRDF query");
|
Chris@480
|
538 query = librdf_new_query
|
Chris@480
|
539 (m_redland->getWorld(), "sparql", NULL,
|
Chris@480
|
540 (const unsigned char *)m_query.toUtf8().data(), uri);
|
Chris@480
|
541 }
|
Chris@480
|
542
|
Chris@480
|
543 if (!query) {
|
Chris@480
|
544 m_errorString = "Failed to construct query";
|
Chris@480
|
545 return list;
|
Chris@480
|
546 }
|
Chris@480
|
547
|
Chris@480
|
548 librdf_query_results *results;
|
Chris@480
|
549 {
|
Chris@480
|
550 Profiler p("SimpleSPARQLQuery: Execute LIBRDF query");
|
Chris@480
|
551 results = librdf_query_execute(query, m_redland->getModel());
|
Chris@480
|
552 }
|
Chris@480
|
553
|
Chris@480
|
554 if (!results) {
|
Chris@480
|
555 cerr << "SimpleSPARQLQuery: LIBRDF query failed" << endl;
|
Chris@480
|
556 librdf_free_query(query);
|
Chris@480
|
557 return list;
|
Chris@480
|
558 }
|
Chris@480
|
559
|
Chris@480
|
560 if (!librdf_query_results_is_bindings(results)) {
|
Chris@480
|
561 cerr << "SimpleSPARQLQuery: LIBRDF query has wrong result type (not bindings)" << endl;
|
Chris@480
|
562 librdf_free_query_results(results);
|
Chris@480
|
563 librdf_free_query(query);
|
Chris@480
|
564 return list;
|
Chris@480
|
565 }
|
Chris@480
|
566
|
Chris@480
|
567 int resultCount = 0;
|
Chris@480
|
568 int resultTotal = librdf_query_results_get_count(results); // probably wrong
|
Chris@480
|
569 m_cancelled = false;
|
Chris@480
|
570
|
Chris@480
|
571 while (!librdf_query_results_finished(results)) {
|
Chris@480
|
572
|
Chris@480
|
573 int count = librdf_query_results_get_bindings_count(results);
|
Chris@480
|
574
|
Chris@480
|
575 KeyValueMap resultmap;
|
Chris@480
|
576
|
Chris@480
|
577 for (int i = 0; i < count; ++i) {
|
Chris@480
|
578
|
Chris@480
|
579 const char *name =
|
Chris@480
|
580 librdf_query_results_get_binding_name(results, i);
|
Chris@480
|
581
|
Chris@480
|
582 librdf_node *node =
|
Chris@480
|
583 librdf_query_results_get_binding_value(results, i);
|
Chris@480
|
584
|
Chris@480
|
585 QString key = (const char *)name;
|
Chris@480
|
586
|
Chris@480
|
587 if (!node) {
|
Chris@480
|
588 resultmap[key] = Value();
|
Chris@480
|
589 continue;
|
Chris@480
|
590 }
|
Chris@480
|
591
|
Chris@480
|
592 ValueType type = LiteralValue;
|
Chris@481
|
593 QString text;
|
Chris@481
|
594
|
Chris@481
|
595 if (librdf_node_is_resource(node)) {
|
Chris@481
|
596
|
Chris@481
|
597 type = URIValue;
|
Chris@481
|
598 librdf_uri *uri = librdf_node_get_uri(node);
|
Chris@481
|
599 text = (const char *)librdf_uri_as_string(uri);
|
Chris@481
|
600
|
Chris@481
|
601 } else if (librdf_node_is_literal(node)) {
|
Chris@481
|
602
|
Chris@481
|
603 type = LiteralValue;
|
Chris@481
|
604 text = (const char *)librdf_node_get_literal_value(node);
|
Chris@481
|
605
|
Chris@481
|
606 } else if (librdf_node_is_blank(node)) {
|
Chris@481
|
607
|
Chris@481
|
608 type = BlankValue;
|
Chris@481
|
609
|
Chris@481
|
610 } else {
|
Chris@481
|
611
|
Chris@480
|
612 cerr << "SimpleSPARQLQuery: LIBRDF query returned unknown node type (not resource, literal, or blank)" << endl;
|
Chris@480
|
613 }
|
Chris@480
|
614
|
Chris@480
|
615 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
|
Chris@481
|
616 cerr << i << ". " << key.toStdString() << " -> " << text.toStdString() << " (type " << type << ")" << endl;
|
Chris@480
|
617 #endif
|
Chris@480
|
618
|
Chris@480
|
619 resultmap[key] = Value(type, text);
|
Chris@480
|
620
|
Chris@480
|
621 librdf_free_node(node);
|
Chris@480
|
622 }
|
Chris@480
|
623
|
Chris@480
|
624 list.push_back(resultmap);
|
Chris@480
|
625
|
Chris@480
|
626 librdf_query_results_next(results);
|
Chris@480
|
627
|
Chris@480
|
628 resultCount++;
|
Chris@480
|
629
|
Chris@480
|
630 if (m_reporter) {
|
Chris@480
|
631 if (resultCount >= resultTotal) {
|
Chris@480
|
632 if (m_reporter->isDefinite()) m_reporter->setDefinite(false);
|
Chris@480
|
633 m_reporter->setProgress(resultCount);
|
Chris@480
|
634 } else {
|
Chris@480
|
635 m_reporter->setProgress((resultCount * 100) / resultTotal);
|
Chris@480
|
636 }
|
Chris@480
|
637
|
Chris@480
|
638 if (m_reporter->wasCancelled()) {
|
Chris@480
|
639 m_cancelled = true;
|
Chris@480
|
640 break;
|
Chris@480
|
641 }
|
Chris@480
|
642 }
|
Chris@480
|
643 }
|
Chris@480
|
644
|
Chris@480
|
645 librdf_free_query_results(results);
|
Chris@480
|
646 librdf_free_query(query);
|
Chris@480
|
647
|
Chris@481
|
648 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
|
Chris@481
|
649 cerr << "All results retrieved (" << resultCount << " of them)" << endl;
|
Chris@481
|
650 #endif
|
Chris@480
|
651
|
Chris@480
|
652 return list;
|
Chris@480
|
653 #endif
|
Chris@480
|
654 }
|
Chris@480
|
655
|
Chris@440
|
656 SimpleSPARQLQuery::Value
|
Chris@480
|
657 SimpleSPARQLQuery::singleResultQuery(QString fromUri,
|
Chris@480
|
658 QString query, QString binding)
|
Chris@440
|
659 {
|
Chris@480
|
660 SimpleSPARQLQuery q(fromUri, query);
|
Chris@440
|
661 ResultList results = q.execute();
|
Chris@440
|
662 if (!q.isOK()) {
|
Chris@440
|
663 cerr << "SimpleSPARQLQuery::singleResultQuery: ERROR: "
|
Chris@440
|
664 << q.getErrorString().toStdString() << endl;
|
Chris@440
|
665 return Value();
|
Chris@440
|
666 }
|
Chris@440
|
667 if (results.empty()) {
|
Chris@440
|
668 return Value();
|
Chris@440
|
669 }
|
Chris@440
|
670 for (int i = 0; i < results.size(); ++i) {
|
Chris@440
|
671 if (results[i].find(binding) != results[i].end() &&
|
Chris@440
|
672 results[i][binding].type != NoValue) {
|
Chris@440
|
673 return results[i][binding];
|
Chris@440
|
674 }
|
Chris@440
|
675 }
|
Chris@440
|
676 return Value();
|
Chris@440
|
677 }
|
Chris@440
|
678
|
Chris@440
|
679
|
Chris@440
|
680
|