Mercurial > hg > svcore
comparison rdf/SimpleSPARQLQuery.cpp @ 439:beb2948baa77
* Merge revisions 1041 to 1130 from sv-rdf-import branch
| author | Chris Cannam | 
|---|---|
| date | Thu, 18 Sep 2008 12:09:32 +0000 | 
| parents | |
| children | 5746c559af15 | 
   comparison
  equal
  deleted
  inserted
  replaced
| 438:32c399d06374 | 439:beb2948baa77 | 
|---|---|
| 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
| 2 | |
| 3 /* | |
| 4 Sonic Visualiser | |
| 5 An audio file viewer and annotation editor. | |
| 6 Centre for Digital Music, Queen Mary, University of London. | |
| 7 This file copyright 2008 QMUL. | |
| 8 | |
| 9 This program is free software; you can redistribute it and/or | |
| 10 modify it under the terms of the GNU General Public License as | |
| 11 published by the Free Software Foundation; either version 2 of the | |
| 12 License, or (at your option) any later version. See the file | |
| 13 COPYING included with this distribution for more information. | |
| 14 */ | |
| 15 | |
| 16 #include "SimpleSPARQLQuery.h" | |
| 17 #include "base/ProgressReporter.h" | |
| 18 | |
| 19 #include <rasqal.h> | |
| 20 | |
| 21 #include <iostream> | |
| 22 | |
| 23 using std::cerr; | |
| 24 using std::endl; | |
| 25 | |
| 26 class SimpleSPARQLQuery::Impl | |
| 27 { | |
| 28 public: | |
| 29 Impl(QString query); | |
| 30 ~Impl(); | |
| 31 | |
| 32 void setProgressReporter(ProgressReporter *reporter) { m_reporter = reporter; } | |
| 33 bool wasCancelled() const { return m_cancelled; } | |
| 34 | |
| 35 ResultList execute(); | |
| 36 | |
| 37 bool isOK() const; | |
| 38 QString getErrorString() const; | |
| 39 | |
| 40 protected: | |
| 41 static void errorHandler(void *, raptor_locator *, const char *); | |
| 42 | |
| 43 static bool m_initialised; | |
| 44 | |
| 45 QString m_query; | |
| 46 QString m_errorString; | |
| 47 ProgressReporter *m_reporter; | |
| 48 bool m_cancelled; | |
| 49 }; | |
| 50 | |
| 51 SimpleSPARQLQuery::SimpleSPARQLQuery(QString query) : | |
| 52 m_impl(new Impl(query)) { } | |
| 53 | |
| 54 SimpleSPARQLQuery::~SimpleSPARQLQuery() | |
| 55 { | |
| 56 delete m_impl; | |
| 57 } | |
| 58 | |
| 59 void | |
| 60 SimpleSPARQLQuery::setProgressReporter(ProgressReporter *reporter) | |
| 61 { | |
| 62 m_impl->setProgressReporter(reporter); | |
| 63 } | |
| 64 | |
| 65 bool | |
| 66 SimpleSPARQLQuery::wasCancelled() const | |
| 67 { | |
| 68 return m_impl->wasCancelled(); | |
| 69 } | |
| 70 | |
| 71 SimpleSPARQLQuery::ResultList | |
| 72 SimpleSPARQLQuery::execute() | |
| 73 { | |
| 74 return m_impl->execute(); | |
| 75 } | |
| 76 | |
| 77 bool | |
| 78 SimpleSPARQLQuery::isOK() const | |
| 79 { | |
| 80 return m_impl->isOK(); | |
| 81 } | |
| 82 | |
| 83 QString | |
| 84 SimpleSPARQLQuery::getErrorString() const | |
| 85 { | |
| 86 return m_impl->getErrorString(); | |
| 87 } | |
| 88 | |
| 89 bool | |
| 90 SimpleSPARQLQuery::Impl::m_initialised = false; | |
| 91 | |
| 92 SimpleSPARQLQuery::Impl::Impl(QString query) : | |
| 93 m_query(query), | |
| 94 m_reporter(0), | |
| 95 m_cancelled(false) | |
| 96 { | |
| 97 //!!! fortunately this global stuff goes away in future rasqal versions | |
| 98 if (!m_initialised) { | |
| 99 rasqal_init(); | |
| 100 } | |
| 101 } | |
| 102 | |
| 103 SimpleSPARQLQuery::Impl::~Impl() | |
| 104 { | |
| 105 //!!! rasqal_finish(); | |
| 106 } | |
| 107 | |
| 108 bool | |
| 109 SimpleSPARQLQuery::Impl::isOK() const | |
| 110 { | |
| 111 return (m_errorString == ""); | |
| 112 } | |
| 113 | |
| 114 QString | |
| 115 SimpleSPARQLQuery::Impl::getErrorString() const | |
| 116 { | |
| 117 return m_errorString; | |
| 118 } | |
| 119 | |
| 120 void | |
| 121 SimpleSPARQLQuery::Impl::errorHandler(void *data, | |
| 122 raptor_locator *locator, | |
| 123 const char *message) | |
| 124 { | |
| 125 SimpleSPARQLQuery::Impl *impl = (SimpleSPARQLQuery::Impl *)data; | |
| 126 | |
| 127 // char buffer[256]; | |
| 128 // raptor_format_locator(buffer, 255, locator); | |
| 129 // impl->m_errorString = QString("%1 - %2").arg(buffer).arg(message); | |
| 130 | |
| 131 impl->m_errorString = message; | |
| 132 | |
| 133 cerr << "SimpleSPARQLQuery: ERROR: " << impl->m_errorString.toStdString() << endl; | |
| 134 } | |
| 135 | |
| 136 SimpleSPARQLQuery::ResultList | |
| 137 SimpleSPARQLQuery::Impl::execute() | |
| 138 { | |
| 139 ResultList list; | |
| 140 | |
| 141 rasqal_query *query = rasqal_new_query("sparql", NULL); | |
| 142 if (!query) { | |
| 143 m_errorString = "Failed to construct query"; | |
| 144 cerr << "SimpleSPARQLQuery: ERROR: " << m_errorString.toStdString() << endl; | |
| 145 return list; | |
| 146 } | |
| 147 | |
| 148 rasqal_query_set_error_handler(query, this, errorHandler); | |
| 149 rasqal_query_set_fatal_error_handler(query, this, errorHandler); | |
| 150 | |
| 151 if (rasqal_query_prepare | |
| 152 (query, (const unsigned char *)m_query.toUtf8().data(), NULL)) { | |
| 153 cerr << "SimpleSPARQLQuery: Failed to prepare query" << endl; | |
| 154 rasqal_free_query(query); | |
| 155 return list; | |
| 156 } | |
| 157 | |
| 158 rasqal_query_results *results = rasqal_query_execute(query); | |
| 159 | |
| 160 // cerr << "Query executed" << endl; | |
| 161 | |
| 162 if (!results) { | |
| 163 cerr << "SimpleSPARQLQuery: RASQAL query failed" << endl; | |
| 164 rasqal_free_query(query); | |
| 165 return list; | |
| 166 } | |
| 167 | |
| 168 if (!rasqal_query_results_is_bindings(results)) { | |
| 169 cerr << "SimpleSPARQLQuery: RASQAL query has wrong result type (not bindings)" << endl; | |
| 170 rasqal_free_query_results(results); | |
| 171 rasqal_free_query(query); | |
| 172 return list; | |
| 173 } | |
| 174 | |
| 175 int resultCount = 0; | |
| 176 int resultTotal = rasqal_query_results_get_count(results); // probably wrong | |
| 177 m_cancelled = false; | |
| 178 | |
| 179 while (!rasqal_query_results_finished(results)) { | |
| 180 | |
| 181 int count = rasqal_query_results_get_bindings_count(results); | |
| 182 | |
| 183 KeyValueMap resultmap; | |
| 184 | |
| 185 for (int i = 0; i < count; ++i) { | |
| 186 | |
| 187 const unsigned char *name = | |
| 188 rasqal_query_results_get_binding_name(results, i); | |
| 189 | |
| 190 rasqal_literal *literal = | |
| 191 rasqal_query_results_get_binding_value(results, i); | |
| 192 | |
| 193 QString key = (const char *)name; | |
| 194 | |
| 195 if (!literal) { | |
| 196 resultmap[key] = Value(); | |
| 197 continue; | |
| 198 } | |
| 199 | |
| 200 ValueType type = LiteralValue; | |
| 201 if (literal->type == RASQAL_LITERAL_URI) type = URIValue; | |
| 202 else if (literal->type == RASQAL_LITERAL_BLANK) type = BlankValue; | |
| 203 | |
| 204 QString text = (const char *)rasqal_literal_as_string(literal); | |
| 205 | |
| 206 resultmap[key] = Value(type, text); | |
| 207 } | |
| 208 | |
| 209 list.push_back(resultmap); | |
| 210 | |
| 211 rasqal_query_results_next(results); | |
| 212 | |
| 213 resultCount++; | |
| 214 | |
| 215 if (m_reporter) { | |
| 216 if (resultCount >= resultTotal) { | |
| 217 if (m_reporter->isDefinite()) m_reporter->setDefinite(false); | |
| 218 m_reporter->setProgress(resultCount); | |
| 219 } else { | |
| 220 m_reporter->setProgress((resultCount * 100) / resultTotal); | |
| 221 } | |
| 222 | |
| 223 if (m_reporter->wasCancelled()) { | |
| 224 m_cancelled = true; | |
| 225 break; | |
| 226 } | |
| 227 } | |
| 228 } | |
| 229 | |
| 230 rasqal_free_query_results(results); | |
| 231 rasqal_free_query(query); | |
| 232 | |
| 233 return list; | |
| 234 } | |
| 235 | 
