comparison rdf/SimpleSPARQLQuery.cpp @ 492:23945cdd7161

* Update RDF query stuff again so as to set up a temporary datastore each time we want to query over an rdf file, instead of using rasqal against the file. Seems the only way to avoid threading and storage management issues when trying to load from a single-source file and perform queries against our main datastore at the same time. Maybe.
author Chris Cannam
date Mon, 24 Nov 2008 16:26:11 +0000
parents c3fb8258e34d
children 3931711b5671
comparison
equal deleted inserted replaced
491:6f8ee19984ad 492:23945cdd7161
21 #include <QMutexLocker> 21 #include <QMutexLocker>
22 #include <QRegExp> 22 #include <QRegExp>
23 23
24 #include <set> 24 #include <set>
25 25
26 #ifdef USE_NEW_RASQAL_API
27 #include <rasqal/rasqal.h>
28 #else
29 #include <rasqal.h>
30 #endif
31
32 #include <redland.h> 26 #include <redland.h>
33 27
34 #define DEBUG_SIMPLE_SPARQL_QUERY 1 28 //#define DEBUG_SIMPLE_SPARQL_QUERY 1
35 29
36 #include <iostream> 30 #include <iostream>
37 31
38 using std::cerr; 32 using std::cerr;
39 using std::endl; 33 using std::endl;
40 34
41 #ifdef USE_NEW_RASQAL_API 35 class WredlandWorldWrapper
42 class WrasqalWorldWrapper // wrong but wromantic, etc
43 { 36 {
44 public: 37 public:
45 WrasqalWorldWrapper() : 38 WredlandWorldWrapper();
46 m_world(0) 39 ~WredlandWorldWrapper();
47 { 40
48 m_world = rasqal_new_world(); 41 bool isOK() const;
49 if (!m_world) { 42
50 cerr << "SimpleSPARQLQuery: ERROR: Failed to create RASQAL world!" << endl; 43 bool loadUriIntoDefaultModel(QString uriString, QString &errorString);
51 return;
52 }
53 /*!!! This appears to be new for 0.9.17?
54 if (rasqal_world_open(m_world)) {
55 cerr << "SimpleSPARQLQuery: ERROR: Failed to open RASQAL world!" << endl;
56 return;
57 }
58 */
59 }
60 ~WrasqalWorldWrapper()
61 {
62 rasqal_free_world(m_world);
63 }
64
65 bool isOK() const { return (m_world != 0); }
66
67 rasqal_world *getWorld() { return m_world; }
68 const rasqal_world *getWorld() const { return m_world; }
69
70 private:
71 rasqal_world *m_world;
72 };
73 #endif
74
75 class WredlandWorldWrapper
76 {
77 public:
78 WredlandWorldWrapper() :
79 m_world(0), m_storage(0), m_model(0)
80 {
81 m_world = librdf_new_world();
82 if (!m_world) {
83 cerr << "SimpleSPARQLQuery: ERROR: Failed to create LIBRDF world!" << endl;
84 return;
85 }
86 librdf_world_open(m_world);
87 m_storage = librdf_new_storage(m_world, "trees", NULL, NULL);
88 if (!m_storage) {
89 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland trees datastore, falling back to memory store" << std::endl;
90 m_storage = librdf_new_storage(m_world, NULL, NULL, NULL);
91 if (!m_storage) {
92 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland memory datastore" << std::endl;
93 return;
94 }
95 }
96 m_model = librdf_new_model(m_world, m_storage, NULL);
97 if (!m_model) {
98 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland data model" << std::endl;
99 return;
100 }
101 }
102
103 ~WredlandWorldWrapper()
104 {
105 while (!m_parsedUris.empty()) {
106 librdf_free_uri(m_parsedUris.begin()->second);
107 m_parsedUris.erase(m_parsedUris.begin());
108 }
109 if (m_model) librdf_free_model(m_model);
110 if (m_storage) librdf_free_storage(m_storage);
111 if (m_world) librdf_free_world(m_world);
112 }
113
114 bool isOK() const { return (m_model != 0); }
115
116 librdf_uri *getUri(QString uriString, QString &errorString)
117 {
118 if (m_parsedUris.find(uriString) != m_parsedUris.end()) {
119 return m_parsedUris[uriString];
120 }
121
122 librdf_uri *uri = librdf_new_uri
123 (m_world, (const unsigned char *)uriString.toUtf8().data());
124 if (!uri) {
125 errorString = "Failed to construct librdf_uri!";
126 return 0;
127 }
128
129 librdf_parser *parser = librdf_new_parser(m_world, "guess", NULL, NULL);
130 if (!parser) {
131 errorString = "Failed to initialise Redland parser";
132 return 0;
133 }
134
135 std::cerr << "About to parse \"" << uriString.toStdString() << "\"" << std::endl;
136
137 Profiler p("SimpleSPARQLQuery: Parse URI into LIBRDF model");
138
139 if (librdf_parser_parse_into_model(parser, uri, NULL, m_model)) {
140
141 errorString = QString("Failed to parse RDF from URI \"%1\"")
142 .arg(uriString);
143 librdf_free_parser(parser);
144 // librdf_free_uri(uri);
145 return 0;
146
147 } else {
148
149 librdf_free_parser(parser);
150 m_parsedUris[uriString] = uri;
151 return uri;
152 }
153 }
154 44
155 librdf_world *getWorld() { return m_world; } 45 librdf_world *getWorld() { return m_world; }
156 const librdf_world *getWorld() const { return m_world; } 46 const librdf_world *getWorld() const { return m_world; }
157 47
158 librdf_model *getModel() { return m_model; } 48 librdf_model *getDefaultModel() { return m_defaultModel; }
159 const librdf_model *getModel() const { return m_model; } 49 const librdf_model *getDefaultModel() const { return m_defaultModel; }
50
51 librdf_model *getModel(QString fromUri);
52 void freeModel(QString forUri);
160 53
161 private: 54 private:
55 QMutex m_mutex;
56
162 librdf_world *m_world; 57 librdf_world *m_world;
163 librdf_storage *m_storage; 58 librdf_storage *m_defaultStorage;
164 librdf_model *m_model; 59 librdf_model *m_defaultModel;
165 60
166 QMutex m_mutex; 61 std::set<QString> m_defaultModelUris;
167 std::map<QString, librdf_uri *> m_parsedUris; 62
63 std::map<QString, librdf_storage *> m_ownStorageUris;
64 std::map<QString, librdf_model *> m_ownModelUris;
65
66 bool loadUri(librdf_model *model, QString uri, QString &errorString);
168 }; 67 };
68
69 WredlandWorldWrapper::WredlandWorldWrapper() :
70 m_world(0), m_defaultStorage(0), m_defaultModel(0)
71 {
72 m_world = librdf_new_world();
73 if (!m_world) {
74 cerr << "SimpleSPARQLQuery: ERROR: Failed to create LIBRDF world!" << endl;
75 return;
76 }
77 librdf_world_open(m_world);
78
79 m_defaultStorage = librdf_new_storage(m_world, "trees", NULL, NULL);
80 if (!m_defaultStorage) {
81 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland trees datastore, falling back to memory store" << std::endl;
82 m_defaultStorage = librdf_new_storage(m_world, NULL, NULL, NULL);
83 if (!m_defaultStorage) {
84 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland memory datastore" << std::endl;
85 return;
86 }
87 }
88 m_defaultModel = librdf_new_model(m_world, m_defaultStorage, NULL);
89 if (!m_defaultModel) {
90 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland data model" << std::endl;
91 return;
92 }
93 }
94
95 WredlandWorldWrapper::~WredlandWorldWrapper()
96 {
97 while (!m_ownModelUris.empty()) {
98 librdf_free_model(m_ownModelUris.begin()->second);
99 m_ownModelUris.erase(m_ownModelUris.begin());
100 }
101 while (!m_ownStorageUris.empty()) {
102 librdf_free_storage(m_ownStorageUris.begin()->second);
103 m_ownStorageUris.erase(m_ownStorageUris.begin());
104 }
105 if (m_defaultModel) librdf_free_model(m_defaultModel);
106 if (m_defaultStorage) librdf_free_storage(m_defaultStorage);
107 if (m_world) librdf_free_world(m_world);
108 }
109
110 bool
111 WredlandWorldWrapper::isOK() const {
112 return (m_defaultModel != 0);
113 }
114
115 bool
116 WredlandWorldWrapper::loadUriIntoDefaultModel(QString uriString, QString &errorString)
117 {
118 QMutexLocker locker(&m_mutex);
119
120 if (m_defaultModelUris.find(uriString) != m_defaultModelUris.end()) {
121 return true;
122 }
123
124 if (loadUri(m_defaultModel, uriString, errorString)) {
125 m_defaultModelUris.insert(uriString);
126 return true;
127 } else {
128 return false;
129 }
130 }
131
132 librdf_model *
133 WredlandWorldWrapper::getModel(QString fromUri)
134 {
135 QMutexLocker locker(&m_mutex);
136 if (fromUri == "") {
137 return getDefaultModel();
138 }
139 if (m_ownModelUris.find(fromUri) != m_ownModelUris.end()) {
140 return m_ownModelUris[fromUri];
141 }
142 librdf_storage *storage = librdf_new_storage(m_world, "trees", NULL, NULL);
143 if (!storage) { // don't warn here, we probably already did it in main ctor
144 storage = librdf_new_storage(m_world, NULL, NULL, NULL);
145 }
146 librdf_model *model = librdf_new_model(m_world, storage, NULL);
147 if (!model) {
148 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to create new model" << std::endl;
149 librdf_free_storage(storage);
150 return 0;
151 }
152 QString err;
153 if (!loadUri(model, fromUri, err)) {
154 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to parse into new model: " << err.toStdString() << std::endl;
155 librdf_free_model(model);
156 librdf_free_storage(storage);
157 m_ownModelUris[fromUri] = 0;
158 return 0;
159 }
160 m_ownModelUris[fromUri] = model;
161 m_ownStorageUris[fromUri] = storage;
162 return model;
163 }
164
165 void
166 WredlandWorldWrapper::freeModel(QString forUri)
167 {
168 QMutexLocker locker(&m_mutex);
169 if (forUri == "") {
170 std::cerr << "SimpleSPARQLQuery::freeModel: ERROR: Can't free default model" << std::endl;
171 return;
172 }
173 if (m_ownModelUris.find(forUri) == m_ownModelUris.end()) {
174 std::cerr << "SimpleSPARQLQuery::freeModel: ERROR: Never heard of this model (uri = \"" << forUri.toStdString() << "\")" << std::endl;
175 return;
176 }
177
178 librdf_model *model = m_ownModelUris[forUri];
179 if (model) librdf_free_model(model);
180 m_ownModelUris.erase(forUri);
181
182 if (m_ownStorageUris.find(forUri) != m_ownStorageUris.end()) {
183 librdf_storage *storage = m_ownStorageUris[forUri];
184 if (storage) librdf_free_storage(storage);
185 m_ownStorageUris.erase(forUri);
186 }
187 }
188
189 bool
190 WredlandWorldWrapper::loadUri(librdf_model *model, QString uri, QString &errorString)
191 {
192 librdf_uri *luri = librdf_new_uri
193 (m_world, (const unsigned char *)uri.toUtf8().data());
194 if (!luri) {
195 errorString = "Failed to construct librdf_uri!";
196 return false;
197 }
198
199 librdf_parser *parser = librdf_new_parser(m_world, "guess", NULL, NULL);
200 if (!parser) {
201 errorString = "Failed to initialise Redland parser";
202 return false;
203 }
204
205 std::cerr << "About to parse \"" << uri.toStdString() << "\"" << std::endl;
206
207 Profiler p("SimpleSPARQLQuery: Parse URI into LIBRDF model");
208
209 if (librdf_parser_parse_into_model(parser, luri, NULL, model)) {
210
211 errorString = QString("Failed to parse RDF from URI \"%1\"")
212 .arg(uri);
213 librdf_free_parser(parser);
214 return false;
215
216 } else {
217
218 librdf_free_parser(parser);
219 return true;
220 }
221 }
222
169 223
170 class SimpleSPARQLQuery::Impl 224 class SimpleSPARQLQuery::Impl
171 { 225 {
172 public: 226 public:
173 Impl(SimpleSPARQLQuery::QueryType, QString query); 227 Impl(SimpleSPARQLQuery::QueryType, QString query);
174 ~Impl(); 228 ~Impl();
175 229
176 static bool addSourceToModel(QString sourceUri); 230 static bool addSourceToModel(QString sourceUri);
231 static void closeSingleSource(QString sourceUri);
177 232
178 void setProgressReporter(ProgressReporter *reporter) { m_reporter = reporter; } 233 void setProgressReporter(ProgressReporter *reporter) { m_reporter = reporter; }
179 bool wasCancelled() const { return m_cancelled; } 234 bool wasCancelled() const { return m_cancelled; }
180 235
181 ResultList execute(); 236 ResultList execute();
182 237
183 bool isOK() const; 238 bool isOK() const;
184 QString getErrorString() const; 239 QString getErrorString() const;
185 240
186 protected: 241 protected:
187 static void errorHandler(void *, raptor_locator *, const char *);
188
189 static QMutex m_mutex; 242 static QMutex m_mutex;
190 243
191 #ifdef USE_NEW_RASQAL_API 244 static WredlandWorldWrapper m_redland;
192 static WrasqalWorldWrapper *m_rasqal;
193 #else
194 static bool m_rasqalInitialised;
195 #endif
196
197 static WredlandWorldWrapper *m_redland;
198 245
199 ResultList executeDirectParser(); 246 ResultList executeDirectParser();
200 ResultList executeDatastore(); 247 ResultList executeDatastore();
248 ResultList executeFor(QString modelUri);
201 249
202 QueryType m_type; 250 QueryType m_type;
203 QString m_query; 251 QString m_query;
204 QString m_errorString; 252 QString m_errorString;
205 ProgressReporter *m_reporter; 253 ProgressReporter *m_reporter;
206 bool m_cancelled; 254 bool m_cancelled;
207 }; 255 };
208 256
209 #ifdef USE_NEW_RASQAL_API 257 WredlandWorldWrapper SimpleSPARQLQuery::Impl::m_redland;
210 WrasqalWorldWrapper *SimpleSPARQLQuery::Impl::m_rasqal = 0;
211 #else
212 bool SimpleSPARQLQuery::Impl::m_rasqalInitialised = false;
213 #endif
214
215 WredlandWorldWrapper *SimpleSPARQLQuery::Impl::m_redland = 0;
216 258
217 QMutex SimpleSPARQLQuery::Impl::m_mutex; 259 QMutex SimpleSPARQLQuery::Impl::m_mutex;
218 260
219 SimpleSPARQLQuery::SimpleSPARQLQuery(QueryType type, QString query) : 261 SimpleSPARQLQuery::SimpleSPARQLQuery(QueryType type, QString query) :
220 m_impl(new Impl(type, query)) 262 m_impl(new Impl(type, query))
258 300
259 bool 301 bool
260 SimpleSPARQLQuery::addSourceToModel(QString sourceUri) 302 SimpleSPARQLQuery::addSourceToModel(QString sourceUri)
261 { 303 {
262 return SimpleSPARQLQuery::Impl::addSourceToModel(sourceUri); 304 return SimpleSPARQLQuery::Impl::addSourceToModel(sourceUri);
305 }
306
307 void
308 SimpleSPARQLQuery::closeSingleSource(QString sourceUri)
309 {
310 SimpleSPARQLQuery::Impl::closeSingleSource(sourceUri);
263 } 311 }
264 312
265 SimpleSPARQLQuery::Impl::Impl(QueryType type, QString query) : 313 SimpleSPARQLQuery::Impl::Impl(QueryType type, QString query) :
266 m_type(type), 314 m_type(type),
267 m_query(query), 315 m_query(query),
268 m_reporter(0), 316 m_reporter(0),
269 m_cancelled(false) 317 m_cancelled(false)
270 { 318 {
271 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
272 std::cerr << "SimpleSPARQLQuery::Impl: Query is: \"" << query.toStdString() << "\"" << std::endl;
273 #endif
274 } 319 }
275 320
276 SimpleSPARQLQuery::Impl::~Impl() 321 SimpleSPARQLQuery::Impl::~Impl()
277 { 322 {
278 } 323 }
287 SimpleSPARQLQuery::Impl::getErrorString() const 332 SimpleSPARQLQuery::Impl::getErrorString() const
288 { 333 {
289 return m_errorString; 334 return m_errorString;
290 } 335 }
291 336
292 void
293 SimpleSPARQLQuery::Impl::errorHandler(void *data,
294 raptor_locator *locator,
295 const char *message)
296 {
297 SimpleSPARQLQuery::Impl *impl = (SimpleSPARQLQuery::Impl *)data;
298
299 char buffer[256];
300 raptor_format_locator(buffer, 255, locator);
301 QString loc(buffer);
302 if (loc != "") {
303 impl->m_errorString = QString("%1 - %2").arg(loc).arg(message);
304 } else {
305 impl->m_errorString = message;
306 }
307
308 cerr << "SimpleSPARQLQuery: ERROR: " << impl->m_errorString.toStdString() << endl;
309 }
310
311 SimpleSPARQLQuery::ResultList 337 SimpleSPARQLQuery::ResultList
312 SimpleSPARQLQuery::Impl::execute() 338 SimpleSPARQLQuery::Impl::execute()
313 { 339 {
314 ResultList list; 340 ResultList list;
315 341
316 QMutexLocker locker(&m_mutex); 342 QMutexLocker locker(&m_mutex);
317 343
318 if (m_type == QueryFromModel) { 344 if (!m_redland.isOK()) {
319 if (!m_redland) { 345 cerr << "ERROR: SimpleSPARQLQuery::execute: Failed to initialise Redland datastore" << endl;
320 // There can be no results, because no sources have been 346 return list;
321 // added to the model yet (m_redland is only created when
322 // addSourceToModel is called)
323 cerr << "SimpleSPARQLQuery::execute: NOTE: No sources have been added to data model yet, so no results are possible" << endl;
324 return list;
325 }
326 }
327
328 if (m_type == QueryFromSingleSource) {
329 #ifdef USE_NEW_RASQAL_API
330 if (!m_rasqal) {
331 m_rasqal = new WrasqalWorldWrapper();
332 if (!m_rasqal->isOK()) {
333 cerr << "ERROR: SimpleSPARQLQuery::execute: Failed to initialise Rasqal query engine" << endl;
334 delete m_rasqal;
335 m_rasqal = 0;
336 return list;
337 }
338 }
339 #else
340 if (!m_rasqalInitialised) {
341 rasqal_init();
342 m_rasqalInitialised = true;
343 }
344 #endif
345 } 347 }
346 348
347 if (m_type == QueryFromSingleSource) { 349 if (m_type == QueryFromSingleSource) {
348 return executeDirectParser(); 350 return executeDirectParser();
349 } else { 351 } else {
350 return executeDatastore(); 352 return executeDatastore();
351 } 353 }
354
355 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
356 if (m_errorString != "") {
357 std::cerr << "SimpleSPARQLQuery::execute: error returned: \""
358 << m_errorString.toStdString() << "\"" << std::endl;
359 }
360 #endif
352 } 361 }
353 362
354 SimpleSPARQLQuery::ResultList 363 SimpleSPARQLQuery::ResultList
355 SimpleSPARQLQuery::Impl::executeDirectParser() 364 SimpleSPARQLQuery::Impl::executeDirectParser()
356 { 365 {
366 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
367 std::cerr << "SimpleSPARQLQuery::executeDirectParser: Query is: \"" << m_query.toStdString() << "\"" << std::endl;
368 #endif
369
357 ResultList list; 370 ResultList list;
358 371
359 Profiler profiler("SimpleSPARQLQuery::executeDirectParser"); 372 Profiler profiler("SimpleSPARQLQuery::executeDirectParser");
360 373
361 #ifdef USE_NEW_RASQAL_API 374 static QRegExp fromRE("from\\s+<([^>]+)>", Qt::CaseInsensitive);
362 rasqal_query *query = rasqal_new_query(m_rasqal->getWorld(), "sparql", NULL); 375 QString fromUri;
363 #else 376
364 rasqal_query *query = rasqal_new_query("sparql", NULL); 377 if (fromRE.indexIn(m_query) < 0) {
378 std::cerr << "SimpleSPARQLQuery::executeDirectParser: Query contains no FROM clause, nothing to parse from" << std::endl;
379 return list;
380 } else {
381 fromUri = fromRE.cap(1);
382 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
383 std::cerr << "SimpleSPARQLQuery::executeDirectParser: FROM URI is <"
384 << fromUri.toStdString() << ">" << std::endl;
365 #endif 385 #endif
386 }
387
388 return executeFor(fromUri);
389 }
390
391 SimpleSPARQLQuery::ResultList
392 SimpleSPARQLQuery::Impl::executeDatastore()
393 {
394 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
395 std::cerr << "SimpleSPARQLQuery::executeDatastore: Query is: \"" << m_query.toStdString() << "\"" << std::endl;
396 #endif
397
398 ResultList list;
399
400 Profiler profiler("SimpleSPARQLQuery::executeDatastore");
401
402 return executeFor("");
403 }
404
405 SimpleSPARQLQuery::ResultList
406 SimpleSPARQLQuery::Impl::executeFor(QString modelUri)
407 {
408 ResultList list;
409 librdf_query *query;
410
411 static std::map<QString, int> counter;
412 if (counter.find(m_query) == counter.end()) counter[m_query] = 1;
413 else ++counter[m_query];
414 std::cerr << "Counter for this query: " << counter[m_query] << std::endl;
415 std::cerr << "Base URI is: \"" << modelUri.toStdString() << "\"" << std::endl;
416
417 {
418 Profiler p("SimpleSPARQLQuery: Prepare LIBRDF query");
419 query = librdf_new_query
420 (m_redland.getWorld(), "sparql", NULL,
421 (const unsigned char *)m_query.toUtf8().data(), NULL);
422 }
423
366 if (!query) { 424 if (!query) {
367 m_errorString = "Failed to construct query"; 425 m_errorString = "Failed to construct query";
368 cerr << "SimpleSPARQLQuery: ERROR: " << m_errorString.toStdString() << endl;
369 return list; 426 return list;
370 } 427 }
371 428
372 rasqal_query_set_error_handler(query, this, errorHandler); 429 librdf_query_results *results;
373 rasqal_query_set_fatal_error_handler(query, this, errorHandler);
374
375 { 430 {
376 Profiler p("SimpleSPARQLQuery: Prepare RASQAL query"); 431 Profiler p("SimpleSPARQLQuery: Execute LIBRDF query");
377 432 results = librdf_query_execute(query, m_redland.getModel(modelUri));
378 if (rasqal_query_prepare 433 }
379 (query, (const unsigned char *)m_query.toUtf8().data(), NULL)) {
380 cerr << "SimpleSPARQLQuery: Failed to prepare query" << endl;
381 rasqal_free_query(query);
382 return list;
383 }
384 }
385
386 rasqal_query_results *results;
387
388 {
389 Profiler p("SimpleSPARQLQuery: Execute RASQAL query");
390 results = rasqal_query_execute(query);
391 }
392
393 // cerr << "Query executed" << endl;
394 434
395 if (!results) { 435 if (!results) {
396 cerr << "SimpleSPARQLQuery: RASQAL query failed" << endl; 436 cerr << "SimpleSPARQLQuery: LIBRDF query failed" << endl;
397 rasqal_free_query(query); 437 librdf_free_query(query);
398 return list; 438 return list;
399 } 439 }
400 440
401 if (!rasqal_query_results_is_bindings(results)) { 441 if (!librdf_query_results_is_bindings(results)) {
402 cerr << "SimpleSPARQLQuery: RASQAL query has wrong result type (not bindings)" << endl; 442 cerr << "SimpleSPARQLQuery: LIBRDF query has wrong result type (not bindings)" << endl;
403 rasqal_free_query_results(results); 443 librdf_free_query_results(results);
404 rasqal_free_query(query); 444 librdf_free_query(query);
405 return list; 445 return list;
406 } 446 }
407 447
408 int resultCount = 0; 448 int resultCount = 0;
409 int resultTotal = rasqal_query_results_get_count(results); // probably wrong 449 int resultTotal = librdf_query_results_get_count(results); // probably wrong
410 m_cancelled = false; 450 m_cancelled = false;
411 451
412 while (!rasqal_query_results_finished(results)) { 452 while (!librdf_query_results_finished(results)) {
413 453
414 int count = rasqal_query_results_get_bindings_count(results); 454 int count = librdf_query_results_get_bindings_count(results);
415 455
416 KeyValueMap resultmap; 456 KeyValueMap resultmap;
417 457
418 for (int i = 0; i < count; ++i) { 458 for (int i = 0; i < count; ++i) {
419 459
420 const unsigned char *name = 460 const char *name =
421 rasqal_query_results_get_binding_name(results, i); 461 librdf_query_results_get_binding_name(results, i);
422 462
423 if (!name) { 463 if (!name) {
424 std::cerr << "WARNING: Result " << i << " of query has no name" << std::endl; 464 std::cerr << "WARNING: Result " << i << " of query has no name" << std::endl;
425 continue; 465 continue;
426 } 466 }
427 467
428 rasqal_literal *literal = 468 librdf_node *node =
429 rasqal_query_results_get_binding_value(results, i); 469 librdf_query_results_get_binding_value(results, i);
430 470
431 QString key = (const char *)name; 471 QString key = (const char *)name;
432 472
433 if (!literal) { 473 if (!node) {
474 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
475 std::cerr << i << ". " << key.toStdString() << " -> (nil)" << std::endl;
476 #endif
434 resultmap[key] = Value(); 477 resultmap[key] = Value();
435 continue; 478 continue;
436 } 479 }
437 480
438 ValueType type = LiteralValue; 481 ValueType type = LiteralValue;
439 if (literal->type == RASQAL_LITERAL_BLANK) type = BlankValue;
440 else if (literal->type == RASQAL_LITERAL_URI) type = URIValue;
441
442 QString text; 482 QString text;
443 const char *lit = (const char *)rasqal_literal_as_string(literal); 483
444 if (!lit) { 484 if (librdf_node_is_resource(node)) {
445 std::cerr << "WARNING: Result " << i << " of query has null value" << std::endl; 485
486 type = URIValue;
487 librdf_uri *uri = librdf_node_get_uri(node);
488 const char *us = (const char *)librdf_uri_as_string(uri);
489
490 if (!us) {
491 std::cerr << "WARNING: Result " << i << " of query claims URI type, but has null URI" << std::endl;
492 } else {
493 text = us;
494 }
495
496 } else if (librdf_node_is_literal(node)) {
497
498 type = LiteralValue;
499
500 const char *lit = (const char *)librdf_node_get_literal_value(node);
501 if (!lit) {
502 std::cerr << "WARNING: Result " << i << " of query claims literal type, but has no literal" << std::endl;
503 } else {
504 text = lit;
505 }
506
507 } else if (librdf_node_is_blank(node)) {
508
509 type = BlankValue;
510
446 } else { 511 } else {
447 text = lit; 512
513 cerr << "SimpleSPARQLQuery: LIBRDF query returned unknown node type (not resource, literal, or blank)" << endl;
448 } 514 }
449 515
450 #ifdef DEBUG_SIMPLE_SPARQL_QUERY 516 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
451 std::cerr << i << ". " << key.toStdString() << " -> " << text.toStdString() << " (type " << type << ")" << std::endl; 517 cerr << i << ". " << key.toStdString() << " -> " << text.toStdString() << " (type " << type << ")" << endl;
452 #endif 518 #endif
453 519
454 resultmap[key] = Value(type, text); 520 resultmap[key] = Value(type, text);
521
522 // librdf_free_node(node);
455 } 523 }
456 524
457 list.push_back(resultmap); 525 list.push_back(resultmap);
458 526
459 rasqal_query_results_next(results); 527 librdf_query_results_next(results);
460 528
461 resultCount++; 529 resultCount++;
462 530
463 if (m_reporter) { 531 if (m_reporter) {
464 if (resultCount >= resultTotal) { 532 if (resultCount >= resultTotal) {
473 break; 541 break;
474 } 542 }
475 } 543 }
476 } 544 }
477 545
478 rasqal_free_query_results(results);
479 rasqal_free_query(query);
480
481 return list;
482 }
483
484 SimpleSPARQLQuery::ResultList
485 SimpleSPARQLQuery::Impl::executeDatastore()
486 {
487 ResultList list;
488
489 Profiler profiler("SimpleSPARQLQuery::executeDatastore");
490
491 /*!!!
492 static std::map<QString, int> counter;
493 if (counter.find(m_query) == counter.end()) counter[m_query] = 1;
494 else ++counter[m_query];
495 std::cerr << "Counter for this query: " << counter[m_query] << std::endl;
496 std::cerr << "Base URI is: \"" << m_fromUri.toStdString() << "\"" << std::endl;
497 */
498
499 librdf_query *query;
500
501 {
502 Profiler p("SimpleSPARQLQuery: Prepare LIBRDF query");
503 query = librdf_new_query
504 (m_redland->getWorld(), "sparql", NULL,
505 (const unsigned char *)m_query.toUtf8().data(), NULL);
506 }
507
508 if (!query) {
509 m_errorString = "Failed to construct query";
510 return list;
511 }
512
513 librdf_query_results *results;
514 {
515 Profiler p("SimpleSPARQLQuery: Execute LIBRDF query");
516 results = librdf_query_execute(query, m_redland->getModel());
517 }
518
519 if (!results) {
520 cerr << "SimpleSPARQLQuery: LIBRDF query failed" << endl;
521 librdf_free_query(query);
522 return list;
523 }
524
525 if (!librdf_query_results_is_bindings(results)) {
526 cerr << "SimpleSPARQLQuery: LIBRDF query has wrong result type (not bindings)" << endl;
527 librdf_free_query_results(results);
528 librdf_free_query(query);
529 return list;
530 }
531
532 int resultCount = 0;
533 int resultTotal = librdf_query_results_get_count(results); // probably wrong
534 m_cancelled = false;
535
536 while (!librdf_query_results_finished(results)) {
537
538 int count = librdf_query_results_get_bindings_count(results);
539
540 KeyValueMap resultmap;
541
542 for (int i = 0; i < count; ++i) {
543
544 const char *name =
545 librdf_query_results_get_binding_name(results, i);
546
547 if (!name) {
548 std::cerr << "WARNING: Result " << i << " of query has no name" << std::endl;
549 continue;
550 }
551
552 librdf_node *node =
553 librdf_query_results_get_binding_value(results, i);
554
555 QString key = (const char *)name;
556
557 if (!node) {
558 resultmap[key] = Value();
559 continue;
560 }
561
562 ValueType type = LiteralValue;
563 QString text;
564
565 if (librdf_node_is_resource(node)) {
566
567 type = URIValue;
568 librdf_uri *uri = librdf_node_get_uri(node);
569 const char *us = (const char *)librdf_uri_as_string(uri);
570
571 if (!us) {
572 std::cerr << "WARNING: Result " << i << " of query claims URI type, but has null URI" << std::endl;
573 } else {
574 text = us;
575 }
576
577 } else if (librdf_node_is_literal(node)) {
578
579 type = LiteralValue;
580
581 const char *lit = (const char *)librdf_node_get_literal_value(node);
582 if (!lit) {
583 std::cerr << "WARNING: Result " << i << " of query claims literal type, but has no literal" << std::endl;
584 } else {
585 text = lit;
586 }
587
588 } else if (librdf_node_is_blank(node)) {
589
590 type = BlankValue;
591
592 } else {
593
594 cerr << "SimpleSPARQLQuery: LIBRDF query returned unknown node type (not resource, literal, or blank)" << endl;
595 }
596
597 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
598 cerr << i << ". " << key.toStdString() << " -> " << text.toStdString() << " (type " << type << ")" << endl;
599 #endif
600
601 resultmap[key] = Value(type, text);
602
603 librdf_free_node(node);
604 }
605
606 list.push_back(resultmap);
607
608 librdf_query_results_next(results);
609
610 resultCount++;
611
612 if (m_reporter) {
613 if (resultCount >= resultTotal) {
614 if (m_reporter->isDefinite()) m_reporter->setDefinite(false);
615 m_reporter->setProgress(resultCount);
616 } else {
617 m_reporter->setProgress((resultCount * 100) / resultTotal);
618 }
619
620 if (m_reporter->wasCancelled()) {
621 m_cancelled = true;
622 break;
623 }
624 }
625 }
626
627 librdf_free_query_results(results); 546 librdf_free_query_results(results);
628 librdf_free_query(query); 547 librdf_free_query(query);
629 548
630 #ifdef DEBUG_SIMPLE_SPARQL_QUERY 549 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
631 cerr << "All results retrieved (" << resultCount << " of them)" << endl; 550 cerr << "SimpleSPARQLQuery::executeDatastore: All results retrieved (" << resultCount << " of them)" << endl;
632 #endif 551 #endif
633 552
634 return list; 553 return list;
635 } 554 }
636 555
639 { 558 {
640 QString err; 559 QString err;
641 560
642 QMutexLocker locker(&m_mutex); 561 QMutexLocker locker(&m_mutex);
643 562
644 if (!m_redland) { 563 if (!m_redland.isOK()) {
645 m_redland = new WredlandWorldWrapper(); 564 std::cerr << "SimpleSPARQLQuery::addSourceToModel: Failed to initialise Redland datastore" << std::endl;
646 if (!m_redland->isOK()) { 565 return false;
647 cerr << "ERROR: SimpleSPARQLQuery::addSourceToModel: Failed to initialise Redland datastore" << endl; 566 }
648 delete m_redland; 567
649 m_redland = 0; 568 if (!m_redland.loadUriIntoDefaultModel(sourceUri, err)) {
650 return false;
651 }
652 }
653
654 librdf_uri *uri = m_redland->getUri(sourceUri, err);
655
656 if (!uri) {
657 std::cerr << "SimpleSPARQLQuery::addSourceToModel: Failed to add source URI \"" << sourceUri.toStdString() << ": " << err.toStdString() << std::endl; 569 std::cerr << "SimpleSPARQLQuery::addSourceToModel: Failed to add source URI \"" << sourceUri.toStdString() << ": " << err.toStdString() << std::endl;
658 return false; 570 return false;
659 } 571 }
660 return true; 572 return true;
573 }
574
575 void
576 SimpleSPARQLQuery::Impl::closeSingleSource(QString sourceUri)
577 {
578 QMutexLocker locker(&m_mutex);
579
580 m_redland.freeModel(sourceUri);
661 } 581 }
662 582
663 SimpleSPARQLQuery::Value 583 SimpleSPARQLQuery::Value
664 SimpleSPARQLQuery::singleResultQuery(QueryType type, 584 SimpleSPARQLQuery::singleResultQuery(QueryType type,
665 QString query, QString binding) 585 QString query, QString binding)