annotate rdf/SimpleSPARQLQuery.cpp @ 555:8accc7969c1c

* Some steps to avoid backward seeks in MatrixFile in common use cases
author Chris Cannam
date Mon, 09 Feb 2009 11:38:08 +0000
parents 3c5570e3d9c5
children 48f869ce8e64
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@526 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@526 271 WredlandWorldWrapper *SimpleSPARQLQuery::Impl::m_redland = 0;
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@526 358 if (!m_redland) {
Chris@526 359 m_redland = new WredlandWorldWrapper();
Chris@526 360 }
Chris@526 361
Chris@526 362 if (!m_redland->isOK()) {
Chris@492 363 cerr << "ERROR: SimpleSPARQLQuery::execute: Failed to initialise Redland datastore" << endl;
Chris@492 364 return list;
Chris@440 365 }
Chris@480 366
Chris@489 367 if (m_type == QueryFromSingleSource) {
Chris@480 368 return executeDirectParser();
Chris@480 369 } else {
Chris@480 370 return executeDatastore();
Chris@480 371 }
Chris@492 372
Chris@492 373 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@492 374 if (m_errorString != "") {
Chris@492 375 std::cerr << "SimpleSPARQLQuery::execute: error returned: \""
Chris@492 376 << m_errorString.toStdString() << "\"" << std::endl;
Chris@492 377 }
Chris@492 378 #endif
Chris@480 379 }
Chris@480 380
Chris@480 381 SimpleSPARQLQuery::ResultList
Chris@480 382 SimpleSPARQLQuery::Impl::executeDirectParser()
Chris@480 383 {
Chris@492 384 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@492 385 std::cerr << "SimpleSPARQLQuery::executeDirectParser: Query is: \"" << m_query.toStdString() << "\"" << std::endl;
Chris@492 386 #endif
Chris@492 387
Chris@480 388 ResultList list;
Chris@480 389
Chris@480 390 Profiler profiler("SimpleSPARQLQuery::executeDirectParser");
Chris@480 391
Chris@492 392 static QRegExp fromRE("from\\s+<([^>]+)>", Qt::CaseInsensitive);
Chris@492 393 QString fromUri;
Chris@492 394
Chris@492 395 if (fromRE.indexIn(m_query) < 0) {
Chris@492 396 std::cerr << "SimpleSPARQLQuery::executeDirectParser: Query contains no FROM clause, nothing to parse from" << std::endl;
Chris@492 397 return list;
Chris@492 398 } else {
Chris@492 399 fromUri = fromRE.cap(1);
Chris@492 400 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@492 401 std::cerr << "SimpleSPARQLQuery::executeDirectParser: FROM URI is <"
Chris@492 402 << fromUri.toStdString() << ">" << std::endl;
Chris@440 403 #endif
Chris@439 404 }
Chris@439 405
Chris@492 406 return executeFor(fromUri);
Chris@439 407 }
Chris@440 408
Chris@480 409 SimpleSPARQLQuery::ResultList
Chris@480 410 SimpleSPARQLQuery::Impl::executeDatastore()
Chris@480 411 {
Chris@492 412 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@492 413 std::cerr << "SimpleSPARQLQuery::executeDatastore: Query is: \"" << m_query.toStdString() << "\"" << std::endl;
Chris@492 414 #endif
Chris@492 415
Chris@480 416 ResultList list;
Chris@489 417
Chris@480 418 Profiler profiler("SimpleSPARQLQuery::executeDatastore");
Chris@480 419
Chris@492 420 return executeFor("");
Chris@492 421 }
Chris@492 422
Chris@492 423 SimpleSPARQLQuery::ResultList
Chris@492 424 SimpleSPARQLQuery::Impl::executeFor(QString modelUri)
Chris@492 425 {
Chris@492 426 ResultList list;
Chris@492 427 librdf_query *query;
Chris@492 428
Chris@493 429 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@480 430 static std::map<QString, int> counter;
Chris@480 431 if (counter.find(m_query) == counter.end()) counter[m_query] = 1;
Chris@480 432 else ++counter[m_query];
Chris@480 433 std::cerr << "Counter for this query: " << counter[m_query] << std::endl;
Chris@492 434 std::cerr << "Base URI is: \"" << modelUri.toStdString() << "\"" << std::endl;
Chris@493 435 #endif
Chris@480 436
Chris@480 437 {
Chris@480 438 Profiler p("SimpleSPARQLQuery: Prepare LIBRDF query");
Chris@480 439 query = librdf_new_query
Chris@526 440 (m_redland->getWorld(), "sparql", NULL,
Chris@489 441 (const unsigned char *)m_query.toUtf8().data(), NULL);
Chris@480 442 }
Chris@480 443
Chris@480 444 if (!query) {
Chris@480 445 m_errorString = "Failed to construct query";
Chris@480 446 return list;
Chris@480 447 }
Chris@480 448
Chris@480 449 librdf_query_results *results;
Chris@480 450 {
Chris@480 451 Profiler p("SimpleSPARQLQuery: Execute LIBRDF query");
Chris@526 452 results = librdf_query_execute(query, m_redland->getModel(modelUri));
Chris@480 453 }
Chris@480 454
Chris@480 455 if (!results) {
Chris@511 456 m_errorString = "RDF query failed";
Chris@480 457 librdf_free_query(query);
Chris@480 458 return list;
Chris@480 459 }
Chris@480 460
Chris@480 461 if (!librdf_query_results_is_bindings(results)) {
Chris@511 462 m_errorString = "RDF query returned non-bindings results";
Chris@480 463 librdf_free_query_results(results);
Chris@480 464 librdf_free_query(query);
Chris@480 465 return list;
Chris@480 466 }
Chris@480 467
Chris@480 468 int resultCount = 0;
Chris@480 469 int resultTotal = librdf_query_results_get_count(results); // probably wrong
Chris@480 470 m_cancelled = false;
Chris@480 471
Chris@480 472 while (!librdf_query_results_finished(results)) {
Chris@480 473
Chris@480 474 int count = librdf_query_results_get_bindings_count(results);
Chris@480 475
Chris@480 476 KeyValueMap resultmap;
Chris@480 477
Chris@480 478 for (int i = 0; i < count; ++i) {
Chris@480 479
Chris@480 480 const char *name =
Chris@480 481 librdf_query_results_get_binding_name(results, i);
Chris@480 482
Chris@490 483 if (!name) {
Chris@490 484 std::cerr << "WARNING: Result " << i << " of query has no name" << std::endl;
Chris@490 485 continue;
Chris@490 486 }
Chris@490 487
Chris@480 488 librdf_node *node =
Chris@480 489 librdf_query_results_get_binding_value(results, i);
Chris@480 490
Chris@480 491 QString key = (const char *)name;
Chris@480 492
Chris@480 493 if (!node) {
Chris@492 494 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@492 495 std::cerr << i << ". " << key.toStdString() << " -> (nil)" << std::endl;
Chris@492 496 #endif
Chris@480 497 resultmap[key] = Value();
Chris@480 498 continue;
Chris@480 499 }
Chris@480 500
Chris@480 501 ValueType type = LiteralValue;
Chris@481 502 QString text;
Chris@481 503
Chris@481 504 if (librdf_node_is_resource(node)) {
Chris@481 505
Chris@481 506 type = URIValue;
Chris@481 507 librdf_uri *uri = librdf_node_get_uri(node);
Chris@490 508 const char *us = (const char *)librdf_uri_as_string(uri);
Chris@490 509
Chris@490 510 if (!us) {
Chris@490 511 std::cerr << "WARNING: Result " << i << " of query claims URI type, but has null URI" << std::endl;
Chris@490 512 } else {
Chris@490 513 text = us;
Chris@490 514 }
Chris@481 515
Chris@481 516 } else if (librdf_node_is_literal(node)) {
Chris@481 517
Chris@481 518 type = LiteralValue;
Chris@490 519
Chris@490 520 const char *lit = (const char *)librdf_node_get_literal_value(node);
Chris@490 521 if (!lit) {
Chris@490 522 std::cerr << "WARNING: Result " << i << " of query claims literal type, but has no literal" << std::endl;
Chris@490 523 } else {
Chris@490 524 text = lit;
Chris@490 525 }
Chris@481 526
Chris@481 527 } else if (librdf_node_is_blank(node)) {
Chris@481 528
Chris@481 529 type = BlankValue;
Chris@481 530
Chris@494 531 const char *lit = (const char *)librdf_node_get_literal_value(node);
Chris@494 532 if (lit) text = lit;
Chris@494 533
Chris@481 534 } else {
Chris@481 535
Chris@480 536 cerr << "SimpleSPARQLQuery: LIBRDF query returned unknown node type (not resource, literal, or blank)" << endl;
Chris@480 537 }
Chris@480 538
Chris@480 539 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@481 540 cerr << i << ". " << key.toStdString() << " -> " << text.toStdString() << " (type " << type << ")" << endl;
Chris@480 541 #endif
Chris@480 542
Chris@480 543 resultmap[key] = Value(type, text);
Chris@480 544
Chris@492 545 // librdf_free_node(node);
Chris@480 546 }
Chris@480 547
Chris@480 548 list.push_back(resultmap);
Chris@480 549
Chris@480 550 librdf_query_results_next(results);
Chris@480 551
Chris@480 552 resultCount++;
Chris@480 553
Chris@480 554 if (m_reporter) {
Chris@480 555 if (resultCount >= resultTotal) {
Chris@480 556 if (m_reporter->isDefinite()) m_reporter->setDefinite(false);
Chris@480 557 m_reporter->setProgress(resultCount);
Chris@480 558 } else {
Chris@480 559 m_reporter->setProgress((resultCount * 100) / resultTotal);
Chris@480 560 }
Chris@480 561
Chris@480 562 if (m_reporter->wasCancelled()) {
Chris@480 563 m_cancelled = true;
Chris@480 564 break;
Chris@480 565 }
Chris@480 566 }
Chris@480 567 }
Chris@480 568
Chris@480 569 librdf_free_query_results(results);
Chris@480 570 librdf_free_query(query);
Chris@480 571
Chris@481 572 #ifdef DEBUG_SIMPLE_SPARQL_QUERY
Chris@492 573 cerr << "SimpleSPARQLQuery::executeDatastore: All results retrieved (" << resultCount << " of them)" << endl;
Chris@481 574 #endif
Chris@480 575
Chris@480 576 return list;
Chris@489 577 }
Chris@489 578
Chris@489 579 bool
Chris@489 580 SimpleSPARQLQuery::Impl::addSourceToModel(QString sourceUri)
Chris@489 581 {
Chris@489 582 QString err;
Chris@489 583
Chris@490 584 QMutexLocker locker(&m_mutex);
Chris@489 585
Chris@527 586 if (!m_redland) {
Chris@527 587 m_redland = new WredlandWorldWrapper();
Chris@527 588 }
Chris@527 589
Chris@526 590 if (!m_redland->isOK()) {
Chris@492 591 std::cerr << "SimpleSPARQLQuery::addSourceToModel: Failed to initialise Redland datastore" << std::endl;
Chris@492 592 return false;
Chris@489 593 }
Chris@489 594
Chris@526 595 if (!m_redland->loadUriIntoDefaultModel(sourceUri, err)) {
Chris@489 596 std::cerr << "SimpleSPARQLQuery::addSourceToModel: Failed to add source URI \"" << sourceUri.toStdString() << ": " << err.toStdString() << std::endl;
Chris@489 597 return false;
Chris@489 598 }
Chris@489 599 return true;
Chris@480 600 }
Chris@480 601
Chris@492 602 void
Chris@492 603 SimpleSPARQLQuery::Impl::closeSingleSource(QString sourceUri)
Chris@492 604 {
Chris@492 605 QMutexLocker locker(&m_mutex);
Chris@492 606
Chris@526 607 m_redland->freeModel(sourceUri);
Chris@492 608 }
Chris@492 609
Chris@440 610 SimpleSPARQLQuery::Value
Chris@489 611 SimpleSPARQLQuery::singleResultQuery(QueryType type,
Chris@480 612 QString query, QString binding)
Chris@440 613 {
Chris@489 614 SimpleSPARQLQuery q(type, query);
Chris@440 615 ResultList results = q.execute();
Chris@440 616 if (!q.isOK()) {
Chris@440 617 cerr << "SimpleSPARQLQuery::singleResultQuery: ERROR: "
Chris@440 618 << q.getErrorString().toStdString() << endl;
Chris@440 619 return Value();
Chris@440 620 }
Chris@440 621 if (results.empty()) {
Chris@440 622 return Value();
Chris@440 623 }
Chris@440 624 for (int i = 0; i < results.size(); ++i) {
Chris@440 625 if (results[i].find(binding) != results[i].end() &&
Chris@440 626 results[i][binding].type != NoValue) {
Chris@440 627 return results[i][binding];
Chris@440 628 }
Chris@440 629 }
Chris@440 630 return Value();
Chris@440 631 }
Chris@440 632
Chris@440 633
Chris@440 634