annotate rdf/SimpleSPARQLQuery.cpp @ 537:3cc4b7cd2aa5

* Merge from one-fftdataserver-per-fftmodel branch. This bit of reworking (which is not described very accurately by the title of the branch) turns the MatrixFile object into something that either reads or writes, but not both, and separates the FFT file cache reader and writer implementations separately. This allows the FFT data server to have a single thread owning writers and one reader per "customer" thread, and for all locking to be vastly simplified and concentrated in the data server alone (because none of the classes it makes use of is used in more than one thread at a time). The result is faster and more trustworthy code.
author Chris Cannam
date Tue, 27 Jan 2009 13:25:10 +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