annotate rdf/SimpleSPARQLQuery.cpp @ 511:7207e3eba44f sv-v1.4rc1

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