diff 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
line wrap: on
line diff
--- a/rdf/SimpleSPARQLQuery.cpp	Fri Nov 21 14:25:33 2008 +0000
+++ b/rdf/SimpleSPARQLQuery.cpp	Fri Nov 21 16:12:29 2008 +0000
@@ -29,9 +29,7 @@
 #include <rasqal.h>
 #endif
 
-#ifdef HAVE_REDLAND
 #include <redland.h>
-#endif
 
 //#define DEBUG_SIMPLE_SPARQL_QUERY 1
 
@@ -64,6 +62,8 @@
         rasqal_free_world(m_world);
     }
 
+    bool isOK() const { return (m_world != 0); }
+
     rasqal_world *getWorld() { return m_world; }
     const rasqal_world *getWorld() const { return m_world; }
 
@@ -72,7 +72,6 @@
 };
 #endif
 
-#ifdef HAVE_REDLAND
 class WredlandWorldWrapper
 {
 public:
@@ -169,14 +168,15 @@
     QMutex m_mutex;
     std::map<QString, librdf_uri *> m_parsedUris;
 };
-#endif
 
 class SimpleSPARQLQuery::Impl
 {
 public:
-    Impl(QString fromUri, QString query);
+    Impl(SimpleSPARQLQuery::QueryType, QString query);
     ~Impl();
 
+    static bool addSourceToModel(QString sourceUri);
+
     void setProgressReporter(ProgressReporter *reporter) { m_reporter = reporter; }
     bool wasCancelled() const { return m_cancelled; }
 
@@ -185,10 +185,6 @@
     bool isOK() const;
     QString getErrorString() const;
 
-    static void setBackEnd(SimpleSPARQLQuery::BackEndPreference p) {
-        m_preference = p;
-    }
-
 protected:
     static void errorHandler(void *, raptor_locator *, const char *);
 
@@ -200,16 +196,12 @@
     static bool m_rasqalInitialised;
 #endif
 
-#ifdef HAVE_REDLAND
     static WredlandWorldWrapper *m_redland;
-#endif
-
-    static SimpleSPARQLQuery::BackEndPreference m_preference;
 
     ResultList executeDirectParser();
     ResultList executeDatastore();
 
-    QString m_fromUri;
+    QueryType m_type;
     QString m_query;
     QString m_errorString;
     ProgressReporter *m_reporter;
@@ -222,17 +214,12 @@
 bool SimpleSPARQLQuery::Impl::m_rasqalInitialised = false;
 #endif
 
-#ifdef HAVE_REDLAND
 WredlandWorldWrapper *SimpleSPARQLQuery::Impl::m_redland = 0;
-#endif
 
 QMutex SimpleSPARQLQuery::Impl::m_mutex;
 
-SimpleSPARQLQuery::BackEndPreference
-SimpleSPARQLQuery::Impl::m_preference = SimpleSPARQLQuery::AutoSelectBackEnd;
-
-SimpleSPARQLQuery::SimpleSPARQLQuery(QString fromUri, QString query) :
-    m_impl(new Impl(fromUri, query))
+SimpleSPARQLQuery::SimpleSPARQLQuery(QueryType type, QString query) :
+    m_impl(new Impl(type, query))
 {
 }
 
@@ -271,14 +258,14 @@
     return m_impl->getErrorString();
 }
 
-void
-SimpleSPARQLQuery::setBackEnd(BackEndPreference p)
+bool
+SimpleSPARQLQuery::addSourceToModel(QString sourceUri)
 {
-    SimpleSPARQLQuery::Impl::setBackEnd(p);
+    return SimpleSPARQLQuery::Impl::addSourceToModel(sourceUri);
 }
 
-SimpleSPARQLQuery::Impl::Impl(QString fromUri, QString query) :
-    m_fromUri(fromUri),
+SimpleSPARQLQuery::Impl::Impl(QueryType type, QString query) :
+    m_type(type),
     m_query(query),
     m_reporter(0),
     m_cancelled(false)
@@ -328,48 +315,32 @@
 {
     ResultList list;
 
-    BackEndPreference preference;
-
     m_mutex.lock();
 
-    if (m_preference == AutoSelectBackEnd) {
-#ifdef HAVE_REDLAND
-//        cerr << "librdf version: " << librdf_version_major << "." << librdf_version_minor << "." << librdf_version_release << endl;
-        if (librdf_version_major > 1 ||
-            (librdf_version_major == 1 &&
-             (librdf_version_minor > 0 ||
-              (librdf_version_minor == 0 &&
-               librdf_version_release > 7)))) {
-            cerr << "SimpleSPARQLQuery: Auto-selecting LIBRDF back-end for tree-based storage" << endl;
-            m_preference = DatastoreBackEnd;
-        }
-#endif
-        if (m_preference == AutoSelectBackEnd) {
-            cerr << "SimpleSPARQLQuery: Auto-selecting RASQAL back-end" << endl;
-            m_preference = DirectParserBackEnd;
+    if (m_type == QueryFromModel) {
+        if (!m_redland) {
+            // There can be no results, because no sources have been
+            // added to the model yet (m_redland is only created when
+            // addSourceToModel is called)
+            cerr << "SimpleSPARQLQuery::execute: NOTE: No sources have been added to data model yet, so no results are possible" << endl;
+            m_mutex.unlock();
+            return list;
         }
     }
 
-    if (m_preference == DatastoreBackEnd) {
-#ifdef HAVE_REDLAND
-        if (!m_redland) {
-            m_redland = new WredlandWorldWrapper();
-            if (!m_redland->isOK()) {
-                cerr << "WARNING: SimpleSPARQLQuery::execute: Failed to initialise Redland datastore, falling back to direct parser implementation" << endl;
-                delete m_redland;
-                m_preference = DirectParserBackEnd;
+    if (m_type == QueryFromSingleSource) {
+#ifdef USE_NEW_RASQAL_API
+        if (!m_rasqal) {
+            m_rasqal = new WrasqalWorldWrapper();
+            if (!m_rasqal->isOK()) {
+                cerr << "ERROR: SimpleSPARQLQuery::execute: Failed to initialise Rasqal query engine" << endl;
+                delete m_rasqal;
+                m_rasqal = 0;
+                m_mutex.unlock();
+                return list;
             }
         }
 #else
-        cerr << "WARNING: SimpleSPARQLQuery::execute: Datastore implementation preference indicated, but no datastore compiled in; using direct parser" << endl;
-        m_preference = DirectParserBackEnd;
-#endif
-    }
-
-    if (m_preference == DirectParserBackEnd) {
-#ifdef USE_NEW_RASQAL_API
-        if (!m_rasqal) m_rasqal = new WrasqalWorldWrapper();
-#else
         if (!m_rasqalInitialised) {
             rasqal_init();
             m_rasqalInitialised = true;
@@ -377,10 +348,9 @@
 #endif
     }
 
-    preference = m_preference;
     m_mutex.unlock();
 
-    if (preference == SimpleSPARQLQuery::DirectParserBackEnd) {
+    if (m_type == QueryFromSingleSource) {
         return executeDirectParser();
     } else {
         return executeDatastore();
@@ -510,19 +480,9 @@
 SimpleSPARQLQuery::Impl::executeDatastore()
 {
     ResultList list;
-#ifndef HAVE_REDLAND
-    // This should have been caught by execute()
-    cerr << "SimpleSPARQLQuery: INTERNAL ERROR: Datastore not compiled in" << endl;
-    return list;
-#else
+
     Profiler profiler("SimpleSPARQLQuery::executeDatastore");
 
-    librdf_uri *uri = m_redland->getUri(m_fromUri, m_errorString);
-    if (!uri) return list;
-
-#ifdef DEBUG_SIMPLE_SPARQL_QUERY
-    std::cerr << "SimpleSPARQLQuery: Query is: \"" << m_query.toStdString() << "\"" << std::endl;
-#endif
 /*!!!
     static std::map<QString, int> counter;
     if (counter.find(m_query) == counter.end()) counter[m_query] = 1;
@@ -537,7 +497,7 @@
         Profiler p("SimpleSPARQLQuery: Prepare LIBRDF query");
         query = librdf_new_query
             (m_redland->getWorld(), "sparql", NULL,
-             (const unsigned char *)m_query.toUtf8().data(), uri);
+             (const unsigned char *)m_query.toUtf8().data(), NULL);
     }
     
     if (!query) {
@@ -650,14 +610,42 @@
 #endif
 
     return list;
-#endif
+}
+
+bool
+SimpleSPARQLQuery::Impl::addSourceToModel(QString sourceUri)
+{
+    QString err;
+
+    m_mutex.lock();
+
+    if (!m_redland) {
+        m_redland = new WredlandWorldWrapper();
+        if (!m_redland->isOK()) {
+            cerr << "ERROR: SimpleSPARQLQuery::addSourceToModel: Failed to initialise Redland datastore" << endl;
+            delete m_redland;
+            m_redland = 0;
+            m_mutex.unlock();
+            return false;
+        }
+    }
+
+    m_mutex.unlock();
+
+    librdf_uri *uri = m_redland->getUri(sourceUri, err);
+
+    if (!uri) {
+        std::cerr << "SimpleSPARQLQuery::addSourceToModel: Failed to add source URI \"" << sourceUri.toStdString() << ": " << err.toStdString() << std::endl;
+        return false;
+    }
+    return true;
 }
 
 SimpleSPARQLQuery::Value
-SimpleSPARQLQuery::singleResultQuery(QString fromUri,
+SimpleSPARQLQuery::singleResultQuery(QueryType type,
                                      QString query, QString binding)
 {
-    SimpleSPARQLQuery q(fromUri, query);
+    SimpleSPARQLQuery q(type, query);
     ResultList results = q.execute();
     if (!q.isOK()) {
         cerr << "SimpleSPARQLQuery::singleResultQuery: ERROR: "