annotate rdf/SimpleSPARQLQuery.cpp @ 718:f3fd2988fc9b

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