Mercurial > hg > svcore
comparison rdf/SimpleSPARQLQuery.cpp @ 489:82ab61fa9223
* Reorganise our sparql queries on the basis that Redland must be
available, not only optional. So for anything querying the pool
of data about plugins, we use a single datastore and model which
is initialised at the outset by PluginRDFIndexer and then queried
directly; for anything that "reads from a file" (e.g. loading
annotations) we query directly using Rasqal, going to the
datastore when we need additional plugin-related information.
This may improve performance, but mostly it simplifies the code
and fixes a serious issue with RDF import in the previous versions
(namely that multiple sequential RDF imports would end up sharing
the same RDF data pool!)
author | Chris Cannam |
---|---|
date | Fri, 21 Nov 2008 16:12:29 +0000 |
parents | a82645e788fc |
children | c3fb8258e34d |
comparison
equal
deleted
inserted
replaced
488:1c66e199e7d9 | 489:82ab61fa9223 |
---|---|
27 #include <rasqal/rasqal.h> | 27 #include <rasqal/rasqal.h> |
28 #else | 28 #else |
29 #include <rasqal.h> | 29 #include <rasqal.h> |
30 #endif | 30 #endif |
31 | 31 |
32 #ifdef HAVE_REDLAND | |
33 #include <redland.h> | 32 #include <redland.h> |
34 #endif | |
35 | 33 |
36 //#define DEBUG_SIMPLE_SPARQL_QUERY 1 | 34 //#define DEBUG_SIMPLE_SPARQL_QUERY 1 |
37 | 35 |
38 #include <iostream> | 36 #include <iostream> |
39 | 37 |
62 ~WrasqalWorldWrapper() | 60 ~WrasqalWorldWrapper() |
63 { | 61 { |
64 rasqal_free_world(m_world); | 62 rasqal_free_world(m_world); |
65 } | 63 } |
66 | 64 |
65 bool isOK() const { return (m_world != 0); } | |
66 | |
67 rasqal_world *getWorld() { return m_world; } | 67 rasqal_world *getWorld() { return m_world; } |
68 const rasqal_world *getWorld() const { return m_world; } | 68 const rasqal_world *getWorld() const { return m_world; } |
69 | 69 |
70 private: | 70 private: |
71 rasqal_world *m_world; | 71 rasqal_world *m_world; |
72 }; | 72 }; |
73 #endif | 73 #endif |
74 | 74 |
75 #ifdef HAVE_REDLAND | |
76 class WredlandWorldWrapper | 75 class WredlandWorldWrapper |
77 { | 76 { |
78 public: | 77 public: |
79 WredlandWorldWrapper() : | 78 WredlandWorldWrapper() : |
80 m_world(0), m_storage(0), m_model(0) | 79 m_world(0), m_storage(0), m_model(0) |
167 librdf_model *m_model; | 166 librdf_model *m_model; |
168 | 167 |
169 QMutex m_mutex; | 168 QMutex m_mutex; |
170 std::map<QString, librdf_uri *> m_parsedUris; | 169 std::map<QString, librdf_uri *> m_parsedUris; |
171 }; | 170 }; |
172 #endif | |
173 | 171 |
174 class SimpleSPARQLQuery::Impl | 172 class SimpleSPARQLQuery::Impl |
175 { | 173 { |
176 public: | 174 public: |
177 Impl(QString fromUri, QString query); | 175 Impl(SimpleSPARQLQuery::QueryType, QString query); |
178 ~Impl(); | 176 ~Impl(); |
177 | |
178 static bool addSourceToModel(QString sourceUri); | |
179 | 179 |
180 void setProgressReporter(ProgressReporter *reporter) { m_reporter = reporter; } | 180 void setProgressReporter(ProgressReporter *reporter) { m_reporter = reporter; } |
181 bool wasCancelled() const { return m_cancelled; } | 181 bool wasCancelled() const { return m_cancelled; } |
182 | 182 |
183 ResultList execute(); | 183 ResultList execute(); |
184 | 184 |
185 bool isOK() const; | 185 bool isOK() const; |
186 QString getErrorString() const; | 186 QString getErrorString() const; |
187 | |
188 static void setBackEnd(SimpleSPARQLQuery::BackEndPreference p) { | |
189 m_preference = p; | |
190 } | |
191 | 187 |
192 protected: | 188 protected: |
193 static void errorHandler(void *, raptor_locator *, const char *); | 189 static void errorHandler(void *, raptor_locator *, const char *); |
194 | 190 |
195 static QMutex m_mutex; | 191 static QMutex m_mutex; |
198 static WrasqalWorldWrapper *m_rasqal; | 194 static WrasqalWorldWrapper *m_rasqal; |
199 #else | 195 #else |
200 static bool m_rasqalInitialised; | 196 static bool m_rasqalInitialised; |
201 #endif | 197 #endif |
202 | 198 |
203 #ifdef HAVE_REDLAND | |
204 static WredlandWorldWrapper *m_redland; | 199 static WredlandWorldWrapper *m_redland; |
205 #endif | |
206 | |
207 static SimpleSPARQLQuery::BackEndPreference m_preference; | |
208 | 200 |
209 ResultList executeDirectParser(); | 201 ResultList executeDirectParser(); |
210 ResultList executeDatastore(); | 202 ResultList executeDatastore(); |
211 | 203 |
212 QString m_fromUri; | 204 QueryType m_type; |
213 QString m_query; | 205 QString m_query; |
214 QString m_errorString; | 206 QString m_errorString; |
215 ProgressReporter *m_reporter; | 207 ProgressReporter *m_reporter; |
216 bool m_cancelled; | 208 bool m_cancelled; |
217 }; | 209 }; |
220 WrasqalWorldWrapper *SimpleSPARQLQuery::Impl::m_rasqal = 0; | 212 WrasqalWorldWrapper *SimpleSPARQLQuery::Impl::m_rasqal = 0; |
221 #else | 213 #else |
222 bool SimpleSPARQLQuery::Impl::m_rasqalInitialised = false; | 214 bool SimpleSPARQLQuery::Impl::m_rasqalInitialised = false; |
223 #endif | 215 #endif |
224 | 216 |
225 #ifdef HAVE_REDLAND | |
226 WredlandWorldWrapper *SimpleSPARQLQuery::Impl::m_redland = 0; | 217 WredlandWorldWrapper *SimpleSPARQLQuery::Impl::m_redland = 0; |
227 #endif | |
228 | 218 |
229 QMutex SimpleSPARQLQuery::Impl::m_mutex; | 219 QMutex SimpleSPARQLQuery::Impl::m_mutex; |
230 | 220 |
231 SimpleSPARQLQuery::BackEndPreference | 221 SimpleSPARQLQuery::SimpleSPARQLQuery(QueryType type, QString query) : |
232 SimpleSPARQLQuery::Impl::m_preference = SimpleSPARQLQuery::AutoSelectBackEnd; | 222 m_impl(new Impl(type, query)) |
233 | |
234 SimpleSPARQLQuery::SimpleSPARQLQuery(QString fromUri, QString query) : | |
235 m_impl(new Impl(fromUri, query)) | |
236 { | 223 { |
237 } | 224 } |
238 | 225 |
239 SimpleSPARQLQuery::~SimpleSPARQLQuery() | 226 SimpleSPARQLQuery::~SimpleSPARQLQuery() |
240 { | 227 { |
269 SimpleSPARQLQuery::getErrorString() const | 256 SimpleSPARQLQuery::getErrorString() const |
270 { | 257 { |
271 return m_impl->getErrorString(); | 258 return m_impl->getErrorString(); |
272 } | 259 } |
273 | 260 |
274 void | 261 bool |
275 SimpleSPARQLQuery::setBackEnd(BackEndPreference p) | 262 SimpleSPARQLQuery::addSourceToModel(QString sourceUri) |
276 { | 263 { |
277 SimpleSPARQLQuery::Impl::setBackEnd(p); | 264 return SimpleSPARQLQuery::Impl::addSourceToModel(sourceUri); |
278 } | 265 } |
279 | 266 |
280 SimpleSPARQLQuery::Impl::Impl(QString fromUri, QString query) : | 267 SimpleSPARQLQuery::Impl::Impl(QueryType type, QString query) : |
281 m_fromUri(fromUri), | 268 m_type(type), |
282 m_query(query), | 269 m_query(query), |
283 m_reporter(0), | 270 m_reporter(0), |
284 m_cancelled(false) | 271 m_cancelled(false) |
285 { | 272 { |
286 #ifdef DEBUG_SIMPLE_SPARQL_QUERY | 273 #ifdef DEBUG_SIMPLE_SPARQL_QUERY |
326 SimpleSPARQLQuery::ResultList | 313 SimpleSPARQLQuery::ResultList |
327 SimpleSPARQLQuery::Impl::execute() | 314 SimpleSPARQLQuery::Impl::execute() |
328 { | 315 { |
329 ResultList list; | 316 ResultList list; |
330 | 317 |
331 BackEndPreference preference; | |
332 | |
333 m_mutex.lock(); | 318 m_mutex.lock(); |
334 | 319 |
335 if (m_preference == AutoSelectBackEnd) { | 320 if (m_type == QueryFromModel) { |
336 #ifdef HAVE_REDLAND | |
337 // cerr << "librdf version: " << librdf_version_major << "." << librdf_version_minor << "." << librdf_version_release << endl; | |
338 if (librdf_version_major > 1 || | |
339 (librdf_version_major == 1 && | |
340 (librdf_version_minor > 0 || | |
341 (librdf_version_minor == 0 && | |
342 librdf_version_release > 7)))) { | |
343 cerr << "SimpleSPARQLQuery: Auto-selecting LIBRDF back-end for tree-based storage" << endl; | |
344 m_preference = DatastoreBackEnd; | |
345 } | |
346 #endif | |
347 if (m_preference == AutoSelectBackEnd) { | |
348 cerr << "SimpleSPARQLQuery: Auto-selecting RASQAL back-end" << endl; | |
349 m_preference = DirectParserBackEnd; | |
350 } | |
351 } | |
352 | |
353 if (m_preference == DatastoreBackEnd) { | |
354 #ifdef HAVE_REDLAND | |
355 if (!m_redland) { | 321 if (!m_redland) { |
356 m_redland = new WredlandWorldWrapper(); | 322 // There can be no results, because no sources have been |
357 if (!m_redland->isOK()) { | 323 // added to the model yet (m_redland is only created when |
358 cerr << "WARNING: SimpleSPARQLQuery::execute: Failed to initialise Redland datastore, falling back to direct parser implementation" << endl; | 324 // addSourceToModel is called) |
359 delete m_redland; | 325 cerr << "SimpleSPARQLQuery::execute: NOTE: No sources have been added to data model yet, so no results are possible" << endl; |
360 m_preference = DirectParserBackEnd; | 326 m_mutex.unlock(); |
361 } | 327 return list; |
362 } | 328 } |
363 #else | 329 } |
364 cerr << "WARNING: SimpleSPARQLQuery::execute: Datastore implementation preference indicated, but no datastore compiled in; using direct parser" << endl; | 330 |
365 m_preference = DirectParserBackEnd; | 331 if (m_type == QueryFromSingleSource) { |
366 #endif | |
367 } | |
368 | |
369 if (m_preference == DirectParserBackEnd) { | |
370 #ifdef USE_NEW_RASQAL_API | 332 #ifdef USE_NEW_RASQAL_API |
371 if (!m_rasqal) m_rasqal = new WrasqalWorldWrapper(); | 333 if (!m_rasqal) { |
334 m_rasqal = new WrasqalWorldWrapper(); | |
335 if (!m_rasqal->isOK()) { | |
336 cerr << "ERROR: SimpleSPARQLQuery::execute: Failed to initialise Rasqal query engine" << endl; | |
337 delete m_rasqal; | |
338 m_rasqal = 0; | |
339 m_mutex.unlock(); | |
340 return list; | |
341 } | |
342 } | |
372 #else | 343 #else |
373 if (!m_rasqalInitialised) { | 344 if (!m_rasqalInitialised) { |
374 rasqal_init(); | 345 rasqal_init(); |
375 m_rasqalInitialised = true; | 346 m_rasqalInitialised = true; |
376 } | 347 } |
377 #endif | 348 #endif |
378 } | 349 } |
379 | 350 |
380 preference = m_preference; | |
381 m_mutex.unlock(); | 351 m_mutex.unlock(); |
382 | 352 |
383 if (preference == SimpleSPARQLQuery::DirectParserBackEnd) { | 353 if (m_type == QueryFromSingleSource) { |
384 return executeDirectParser(); | 354 return executeDirectParser(); |
385 } else { | 355 } else { |
386 return executeDatastore(); | 356 return executeDatastore(); |
387 } | 357 } |
388 } | 358 } |
508 | 478 |
509 SimpleSPARQLQuery::ResultList | 479 SimpleSPARQLQuery::ResultList |
510 SimpleSPARQLQuery::Impl::executeDatastore() | 480 SimpleSPARQLQuery::Impl::executeDatastore() |
511 { | 481 { |
512 ResultList list; | 482 ResultList list; |
513 #ifndef HAVE_REDLAND | 483 |
514 // This should have been caught by execute() | |
515 cerr << "SimpleSPARQLQuery: INTERNAL ERROR: Datastore not compiled in" << endl; | |
516 return list; | |
517 #else | |
518 Profiler profiler("SimpleSPARQLQuery::executeDatastore"); | 484 Profiler profiler("SimpleSPARQLQuery::executeDatastore"); |
519 | 485 |
520 librdf_uri *uri = m_redland->getUri(m_fromUri, m_errorString); | |
521 if (!uri) return list; | |
522 | |
523 #ifdef DEBUG_SIMPLE_SPARQL_QUERY | |
524 std::cerr << "SimpleSPARQLQuery: Query is: \"" << m_query.toStdString() << "\"" << std::endl; | |
525 #endif | |
526 /*!!! | 486 /*!!! |
527 static std::map<QString, int> counter; | 487 static std::map<QString, int> counter; |
528 if (counter.find(m_query) == counter.end()) counter[m_query] = 1; | 488 if (counter.find(m_query) == counter.end()) counter[m_query] = 1; |
529 else ++counter[m_query]; | 489 else ++counter[m_query]; |
530 std::cerr << "Counter for this query: " << counter[m_query] << std::endl; | 490 std::cerr << "Counter for this query: " << counter[m_query] << std::endl; |
535 | 495 |
536 { | 496 { |
537 Profiler p("SimpleSPARQLQuery: Prepare LIBRDF query"); | 497 Profiler p("SimpleSPARQLQuery: Prepare LIBRDF query"); |
538 query = librdf_new_query | 498 query = librdf_new_query |
539 (m_redland->getWorld(), "sparql", NULL, | 499 (m_redland->getWorld(), "sparql", NULL, |
540 (const unsigned char *)m_query.toUtf8().data(), uri); | 500 (const unsigned char *)m_query.toUtf8().data(), NULL); |
541 } | 501 } |
542 | 502 |
543 if (!query) { | 503 if (!query) { |
544 m_errorString = "Failed to construct query"; | 504 m_errorString = "Failed to construct query"; |
545 return list; | 505 return list; |
648 #ifdef DEBUG_SIMPLE_SPARQL_QUERY | 608 #ifdef DEBUG_SIMPLE_SPARQL_QUERY |
649 cerr << "All results retrieved (" << resultCount << " of them)" << endl; | 609 cerr << "All results retrieved (" << resultCount << " of them)" << endl; |
650 #endif | 610 #endif |
651 | 611 |
652 return list; | 612 return list; |
653 #endif | 613 } |
614 | |
615 bool | |
616 SimpleSPARQLQuery::Impl::addSourceToModel(QString sourceUri) | |
617 { | |
618 QString err; | |
619 | |
620 m_mutex.lock(); | |
621 | |
622 if (!m_redland) { | |
623 m_redland = new WredlandWorldWrapper(); | |
624 if (!m_redland->isOK()) { | |
625 cerr << "ERROR: SimpleSPARQLQuery::addSourceToModel: Failed to initialise Redland datastore" << endl; | |
626 delete m_redland; | |
627 m_redland = 0; | |
628 m_mutex.unlock(); | |
629 return false; | |
630 } | |
631 } | |
632 | |
633 m_mutex.unlock(); | |
634 | |
635 librdf_uri *uri = m_redland->getUri(sourceUri, err); | |
636 | |
637 if (!uri) { | |
638 std::cerr << "SimpleSPARQLQuery::addSourceToModel: Failed to add source URI \"" << sourceUri.toStdString() << ": " << err.toStdString() << std::endl; | |
639 return false; | |
640 } | |
641 return true; | |
654 } | 642 } |
655 | 643 |
656 SimpleSPARQLQuery::Value | 644 SimpleSPARQLQuery::Value |
657 SimpleSPARQLQuery::singleResultQuery(QString fromUri, | 645 SimpleSPARQLQuery::singleResultQuery(QueryType type, |
658 QString query, QString binding) | 646 QString query, QString binding) |
659 { | 647 { |
660 SimpleSPARQLQuery q(fromUri, query); | 648 SimpleSPARQLQuery q(type, query); |
661 ResultList results = q.execute(); | 649 ResultList results = q.execute(); |
662 if (!q.isOK()) { | 650 if (!q.isOK()) { |
663 cerr << "SimpleSPARQLQuery::singleResultQuery: ERROR: " | 651 cerr << "SimpleSPARQLQuery::singleResultQuery: ERROR: " |
664 << q.getErrorString().toStdString() << endl; | 652 << q.getErrorString().toStdString() << endl; |
665 return Value(); | 653 return Value(); |