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