annotate rdf/SimpleSPARQLQuery.cpp @ 480:3ffce691c9bf

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