Mercurial > hg > svcore
comparison rdf/SimpleSPARQLQuery.cpp @ 492:23945cdd7161
* Update RDF query stuff again so as to set up a temporary datastore
each time we want to query over an rdf file, instead of using rasqal
against the file. Seems the only way to avoid threading and storage
management issues when trying to load from a single-source file and
perform queries against our main datastore at the same time. Maybe.
author | Chris Cannam |
---|---|
date | Mon, 24 Nov 2008 16:26:11 +0000 |
parents | c3fb8258e34d |
children | 3931711b5671 |
comparison
equal
deleted
inserted
replaced
491:6f8ee19984ad | 492:23945cdd7161 |
---|---|
21 #include <QMutexLocker> | 21 #include <QMutexLocker> |
22 #include <QRegExp> | 22 #include <QRegExp> |
23 | 23 |
24 #include <set> | 24 #include <set> |
25 | 25 |
26 #ifdef USE_NEW_RASQAL_API | |
27 #include <rasqal/rasqal.h> | |
28 #else | |
29 #include <rasqal.h> | |
30 #endif | |
31 | |
32 #include <redland.h> | 26 #include <redland.h> |
33 | 27 |
34 #define DEBUG_SIMPLE_SPARQL_QUERY 1 | 28 //#define DEBUG_SIMPLE_SPARQL_QUERY 1 |
35 | 29 |
36 #include <iostream> | 30 #include <iostream> |
37 | 31 |
38 using std::cerr; | 32 using std::cerr; |
39 using std::endl; | 33 using std::endl; |
40 | 34 |
41 #ifdef USE_NEW_RASQAL_API | 35 class WredlandWorldWrapper |
42 class WrasqalWorldWrapper // wrong but wromantic, etc | |
43 { | 36 { |
44 public: | 37 public: |
45 WrasqalWorldWrapper() : | 38 WredlandWorldWrapper(); |
46 m_world(0) | 39 ~WredlandWorldWrapper(); |
47 { | 40 |
48 m_world = rasqal_new_world(); | 41 bool isOK() const; |
49 if (!m_world) { | 42 |
50 cerr << "SimpleSPARQLQuery: ERROR: Failed to create RASQAL world!" << endl; | 43 bool loadUriIntoDefaultModel(QString uriString, QString &errorString); |
51 return; | |
52 } | |
53 /*!!! This appears to be new for 0.9.17? | |
54 if (rasqal_world_open(m_world)) { | |
55 cerr << "SimpleSPARQLQuery: ERROR: Failed to open RASQAL world!" << endl; | |
56 return; | |
57 } | |
58 */ | |
59 } | |
60 ~WrasqalWorldWrapper() | |
61 { | |
62 rasqal_free_world(m_world); | |
63 } | |
64 | |
65 bool isOK() const { return (m_world != 0); } | |
66 | |
67 rasqal_world *getWorld() { return m_world; } | |
68 const rasqal_world *getWorld() const { return m_world; } | |
69 | |
70 private: | |
71 rasqal_world *m_world; | |
72 }; | |
73 #endif | |
74 | |
75 class WredlandWorldWrapper | |
76 { | |
77 public: | |
78 WredlandWorldWrapper() : | |
79 m_world(0), m_storage(0), m_model(0) | |
80 { | |
81 m_world = librdf_new_world(); | |
82 if (!m_world) { | |
83 cerr << "SimpleSPARQLQuery: ERROR: Failed to create LIBRDF world!" << endl; | |
84 return; | |
85 } | |
86 librdf_world_open(m_world); | |
87 m_storage = librdf_new_storage(m_world, "trees", NULL, NULL); | |
88 if (!m_storage) { | |
89 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland trees datastore, falling back to memory store" << std::endl; | |
90 m_storage = librdf_new_storage(m_world, NULL, NULL, NULL); | |
91 if (!m_storage) { | |
92 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland memory datastore" << std::endl; | |
93 return; | |
94 } | |
95 } | |
96 m_model = librdf_new_model(m_world, m_storage, NULL); | |
97 if (!m_model) { | |
98 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland data model" << std::endl; | |
99 return; | |
100 } | |
101 } | |
102 | |
103 ~WredlandWorldWrapper() | |
104 { | |
105 while (!m_parsedUris.empty()) { | |
106 librdf_free_uri(m_parsedUris.begin()->second); | |
107 m_parsedUris.erase(m_parsedUris.begin()); | |
108 } | |
109 if (m_model) librdf_free_model(m_model); | |
110 if (m_storage) librdf_free_storage(m_storage); | |
111 if (m_world) librdf_free_world(m_world); | |
112 } | |
113 | |
114 bool isOK() const { return (m_model != 0); } | |
115 | |
116 librdf_uri *getUri(QString uriString, QString &errorString) | |
117 { | |
118 if (m_parsedUris.find(uriString) != m_parsedUris.end()) { | |
119 return m_parsedUris[uriString]; | |
120 } | |
121 | |
122 librdf_uri *uri = librdf_new_uri | |
123 (m_world, (const unsigned char *)uriString.toUtf8().data()); | |
124 if (!uri) { | |
125 errorString = "Failed to construct librdf_uri!"; | |
126 return 0; | |
127 } | |
128 | |
129 librdf_parser *parser = librdf_new_parser(m_world, "guess", NULL, NULL); | |
130 if (!parser) { | |
131 errorString = "Failed to initialise Redland parser"; | |
132 return 0; | |
133 } | |
134 | |
135 std::cerr << "About to parse \"" << uriString.toStdString() << "\"" << std::endl; | |
136 | |
137 Profiler p("SimpleSPARQLQuery: Parse URI into LIBRDF model"); | |
138 | |
139 if (librdf_parser_parse_into_model(parser, uri, NULL, m_model)) { | |
140 | |
141 errorString = QString("Failed to parse RDF from URI \"%1\"") | |
142 .arg(uriString); | |
143 librdf_free_parser(parser); | |
144 // librdf_free_uri(uri); | |
145 return 0; | |
146 | |
147 } else { | |
148 | |
149 librdf_free_parser(parser); | |
150 m_parsedUris[uriString] = uri; | |
151 return uri; | |
152 } | |
153 } | |
154 | 44 |
155 librdf_world *getWorld() { return m_world; } | 45 librdf_world *getWorld() { return m_world; } |
156 const librdf_world *getWorld() const { return m_world; } | 46 const librdf_world *getWorld() const { return m_world; } |
157 | 47 |
158 librdf_model *getModel() { return m_model; } | 48 librdf_model *getDefaultModel() { return m_defaultModel; } |
159 const librdf_model *getModel() const { return m_model; } | 49 const librdf_model *getDefaultModel() const { return m_defaultModel; } |
50 | |
51 librdf_model *getModel(QString fromUri); | |
52 void freeModel(QString forUri); | |
160 | 53 |
161 private: | 54 private: |
55 QMutex m_mutex; | |
56 | |
162 librdf_world *m_world; | 57 librdf_world *m_world; |
163 librdf_storage *m_storage; | 58 librdf_storage *m_defaultStorage; |
164 librdf_model *m_model; | 59 librdf_model *m_defaultModel; |
165 | 60 |
166 QMutex m_mutex; | 61 std::set<QString> m_defaultModelUris; |
167 std::map<QString, librdf_uri *> m_parsedUris; | 62 |
63 std::map<QString, librdf_storage *> m_ownStorageUris; | |
64 std::map<QString, librdf_model *> m_ownModelUris; | |
65 | |
66 bool loadUri(librdf_model *model, QString uri, QString &errorString); | |
168 }; | 67 }; |
68 | |
69 WredlandWorldWrapper::WredlandWorldWrapper() : | |
70 m_world(0), m_defaultStorage(0), m_defaultModel(0) | |
71 { | |
72 m_world = librdf_new_world(); | |
73 if (!m_world) { | |
74 cerr << "SimpleSPARQLQuery: ERROR: Failed to create LIBRDF world!" << endl; | |
75 return; | |
76 } | |
77 librdf_world_open(m_world); | |
78 | |
79 m_defaultStorage = librdf_new_storage(m_world, "trees", NULL, NULL); | |
80 if (!m_defaultStorage) { | |
81 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland trees datastore, falling back to memory store" << std::endl; | |
82 m_defaultStorage = librdf_new_storage(m_world, NULL, NULL, NULL); | |
83 if (!m_defaultStorage) { | |
84 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland memory datastore" << std::endl; | |
85 return; | |
86 } | |
87 } | |
88 m_defaultModel = librdf_new_model(m_world, m_defaultStorage, NULL); | |
89 if (!m_defaultModel) { | |
90 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to initialise Redland data model" << std::endl; | |
91 return; | |
92 } | |
93 } | |
94 | |
95 WredlandWorldWrapper::~WredlandWorldWrapper() | |
96 { | |
97 while (!m_ownModelUris.empty()) { | |
98 librdf_free_model(m_ownModelUris.begin()->second); | |
99 m_ownModelUris.erase(m_ownModelUris.begin()); | |
100 } | |
101 while (!m_ownStorageUris.empty()) { | |
102 librdf_free_storage(m_ownStorageUris.begin()->second); | |
103 m_ownStorageUris.erase(m_ownStorageUris.begin()); | |
104 } | |
105 if (m_defaultModel) librdf_free_model(m_defaultModel); | |
106 if (m_defaultStorage) librdf_free_storage(m_defaultStorage); | |
107 if (m_world) librdf_free_world(m_world); | |
108 } | |
109 | |
110 bool | |
111 WredlandWorldWrapper::isOK() const { | |
112 return (m_defaultModel != 0); | |
113 } | |
114 | |
115 bool | |
116 WredlandWorldWrapper::loadUriIntoDefaultModel(QString uriString, QString &errorString) | |
117 { | |
118 QMutexLocker locker(&m_mutex); | |
119 | |
120 if (m_defaultModelUris.find(uriString) != m_defaultModelUris.end()) { | |
121 return true; | |
122 } | |
123 | |
124 if (loadUri(m_defaultModel, uriString, errorString)) { | |
125 m_defaultModelUris.insert(uriString); | |
126 return true; | |
127 } else { | |
128 return false; | |
129 } | |
130 } | |
131 | |
132 librdf_model * | |
133 WredlandWorldWrapper::getModel(QString fromUri) | |
134 { | |
135 QMutexLocker locker(&m_mutex); | |
136 if (fromUri == "") { | |
137 return getDefaultModel(); | |
138 } | |
139 if (m_ownModelUris.find(fromUri) != m_ownModelUris.end()) { | |
140 return m_ownModelUris[fromUri]; | |
141 } | |
142 librdf_storage *storage = librdf_new_storage(m_world, "trees", NULL, NULL); | |
143 if (!storage) { // don't warn here, we probably already did it in main ctor | |
144 storage = librdf_new_storage(m_world, NULL, NULL, NULL); | |
145 } | |
146 librdf_model *model = librdf_new_model(m_world, storage, NULL); | |
147 if (!model) { | |
148 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to create new model" << std::endl; | |
149 librdf_free_storage(storage); | |
150 return 0; | |
151 } | |
152 QString err; | |
153 if (!loadUri(model, fromUri, err)) { | |
154 std::cerr << "SimpleSPARQLQuery: ERROR: Failed to parse into new model: " << err.toStdString() << std::endl; | |
155 librdf_free_model(model); | |
156 librdf_free_storage(storage); | |
157 m_ownModelUris[fromUri] = 0; | |
158 return 0; | |
159 } | |
160 m_ownModelUris[fromUri] = model; | |
161 m_ownStorageUris[fromUri] = storage; | |
162 return model; | |
163 } | |
164 | |
165 void | |
166 WredlandWorldWrapper::freeModel(QString forUri) | |
167 { | |
168 QMutexLocker locker(&m_mutex); | |
169 if (forUri == "") { | |
170 std::cerr << "SimpleSPARQLQuery::freeModel: ERROR: Can't free default model" << std::endl; | |
171 return; | |
172 } | |
173 if (m_ownModelUris.find(forUri) == m_ownModelUris.end()) { | |
174 std::cerr << "SimpleSPARQLQuery::freeModel: ERROR: Never heard of this model (uri = \"" << forUri.toStdString() << "\")" << std::endl; | |
175 return; | |
176 } | |
177 | |
178 librdf_model *model = m_ownModelUris[forUri]; | |
179 if (model) librdf_free_model(model); | |
180 m_ownModelUris.erase(forUri); | |
181 | |
182 if (m_ownStorageUris.find(forUri) != m_ownStorageUris.end()) { | |
183 librdf_storage *storage = m_ownStorageUris[forUri]; | |
184 if (storage) librdf_free_storage(storage); | |
185 m_ownStorageUris.erase(forUri); | |
186 } | |
187 } | |
188 | |
189 bool | |
190 WredlandWorldWrapper::loadUri(librdf_model *model, QString uri, QString &errorString) | |
191 { | |
192 librdf_uri *luri = librdf_new_uri | |
193 (m_world, (const unsigned char *)uri.toUtf8().data()); | |
194 if (!luri) { | |
195 errorString = "Failed to construct librdf_uri!"; | |
196 return false; | |
197 } | |
198 | |
199 librdf_parser *parser = librdf_new_parser(m_world, "guess", NULL, NULL); | |
200 if (!parser) { | |
201 errorString = "Failed to initialise Redland parser"; | |
202 return false; | |
203 } | |
204 | |
205 std::cerr << "About to parse \"" << uri.toStdString() << "\"" << std::endl; | |
206 | |
207 Profiler p("SimpleSPARQLQuery: Parse URI into LIBRDF model"); | |
208 | |
209 if (librdf_parser_parse_into_model(parser, luri, NULL, model)) { | |
210 | |
211 errorString = QString("Failed to parse RDF from URI \"%1\"") | |
212 .arg(uri); | |
213 librdf_free_parser(parser); | |
214 return false; | |
215 | |
216 } else { | |
217 | |
218 librdf_free_parser(parser); | |
219 return true; | |
220 } | |
221 } | |
222 | |
169 | 223 |
170 class SimpleSPARQLQuery::Impl | 224 class SimpleSPARQLQuery::Impl |
171 { | 225 { |
172 public: | 226 public: |
173 Impl(SimpleSPARQLQuery::QueryType, QString query); | 227 Impl(SimpleSPARQLQuery::QueryType, QString query); |
174 ~Impl(); | 228 ~Impl(); |
175 | 229 |
176 static bool addSourceToModel(QString sourceUri); | 230 static bool addSourceToModel(QString sourceUri); |
231 static void closeSingleSource(QString sourceUri); | |
177 | 232 |
178 void setProgressReporter(ProgressReporter *reporter) { m_reporter = reporter; } | 233 void setProgressReporter(ProgressReporter *reporter) { m_reporter = reporter; } |
179 bool wasCancelled() const { return m_cancelled; } | 234 bool wasCancelled() const { return m_cancelled; } |
180 | 235 |
181 ResultList execute(); | 236 ResultList execute(); |
182 | 237 |
183 bool isOK() const; | 238 bool isOK() const; |
184 QString getErrorString() const; | 239 QString getErrorString() const; |
185 | 240 |
186 protected: | 241 protected: |
187 static void errorHandler(void *, raptor_locator *, const char *); | |
188 | |
189 static QMutex m_mutex; | 242 static QMutex m_mutex; |
190 | 243 |
191 #ifdef USE_NEW_RASQAL_API | 244 static WredlandWorldWrapper m_redland; |
192 static WrasqalWorldWrapper *m_rasqal; | |
193 #else | |
194 static bool m_rasqalInitialised; | |
195 #endif | |
196 | |
197 static WredlandWorldWrapper *m_redland; | |
198 | 245 |
199 ResultList executeDirectParser(); | 246 ResultList executeDirectParser(); |
200 ResultList executeDatastore(); | 247 ResultList executeDatastore(); |
248 ResultList executeFor(QString modelUri); | |
201 | 249 |
202 QueryType m_type; | 250 QueryType m_type; |
203 QString m_query; | 251 QString m_query; |
204 QString m_errorString; | 252 QString m_errorString; |
205 ProgressReporter *m_reporter; | 253 ProgressReporter *m_reporter; |
206 bool m_cancelled; | 254 bool m_cancelled; |
207 }; | 255 }; |
208 | 256 |
209 #ifdef USE_NEW_RASQAL_API | 257 WredlandWorldWrapper SimpleSPARQLQuery::Impl::m_redland; |
210 WrasqalWorldWrapper *SimpleSPARQLQuery::Impl::m_rasqal = 0; | |
211 #else | |
212 bool SimpleSPARQLQuery::Impl::m_rasqalInitialised = false; | |
213 #endif | |
214 | |
215 WredlandWorldWrapper *SimpleSPARQLQuery::Impl::m_redland = 0; | |
216 | 258 |
217 QMutex SimpleSPARQLQuery::Impl::m_mutex; | 259 QMutex SimpleSPARQLQuery::Impl::m_mutex; |
218 | 260 |
219 SimpleSPARQLQuery::SimpleSPARQLQuery(QueryType type, QString query) : | 261 SimpleSPARQLQuery::SimpleSPARQLQuery(QueryType type, QString query) : |
220 m_impl(new Impl(type, query)) | 262 m_impl(new Impl(type, query)) |
258 | 300 |
259 bool | 301 bool |
260 SimpleSPARQLQuery::addSourceToModel(QString sourceUri) | 302 SimpleSPARQLQuery::addSourceToModel(QString sourceUri) |
261 { | 303 { |
262 return SimpleSPARQLQuery::Impl::addSourceToModel(sourceUri); | 304 return SimpleSPARQLQuery::Impl::addSourceToModel(sourceUri); |
305 } | |
306 | |
307 void | |
308 SimpleSPARQLQuery::closeSingleSource(QString sourceUri) | |
309 { | |
310 SimpleSPARQLQuery::Impl::closeSingleSource(sourceUri); | |
263 } | 311 } |
264 | 312 |
265 SimpleSPARQLQuery::Impl::Impl(QueryType type, QString query) : | 313 SimpleSPARQLQuery::Impl::Impl(QueryType type, QString query) : |
266 m_type(type), | 314 m_type(type), |
267 m_query(query), | 315 m_query(query), |
268 m_reporter(0), | 316 m_reporter(0), |
269 m_cancelled(false) | 317 m_cancelled(false) |
270 { | 318 { |
271 #ifdef DEBUG_SIMPLE_SPARQL_QUERY | |
272 std::cerr << "SimpleSPARQLQuery::Impl: Query is: \"" << query.toStdString() << "\"" << std::endl; | |
273 #endif | |
274 } | 319 } |
275 | 320 |
276 SimpleSPARQLQuery::Impl::~Impl() | 321 SimpleSPARQLQuery::Impl::~Impl() |
277 { | 322 { |
278 } | 323 } |
287 SimpleSPARQLQuery::Impl::getErrorString() const | 332 SimpleSPARQLQuery::Impl::getErrorString() const |
288 { | 333 { |
289 return m_errorString; | 334 return m_errorString; |
290 } | 335 } |
291 | 336 |
292 void | |
293 SimpleSPARQLQuery::Impl::errorHandler(void *data, | |
294 raptor_locator *locator, | |
295 const char *message) | |
296 { | |
297 SimpleSPARQLQuery::Impl *impl = (SimpleSPARQLQuery::Impl *)data; | |
298 | |
299 char buffer[256]; | |
300 raptor_format_locator(buffer, 255, locator); | |
301 QString loc(buffer); | |
302 if (loc != "") { | |
303 impl->m_errorString = QString("%1 - %2").arg(loc).arg(message); | |
304 } else { | |
305 impl->m_errorString = message; | |
306 } | |
307 | |
308 cerr << "SimpleSPARQLQuery: ERROR: " << impl->m_errorString.toStdString() << endl; | |
309 } | |
310 | |
311 SimpleSPARQLQuery::ResultList | 337 SimpleSPARQLQuery::ResultList |
312 SimpleSPARQLQuery::Impl::execute() | 338 SimpleSPARQLQuery::Impl::execute() |
313 { | 339 { |
314 ResultList list; | 340 ResultList list; |
315 | 341 |
316 QMutexLocker locker(&m_mutex); | 342 QMutexLocker locker(&m_mutex); |
317 | 343 |
318 if (m_type == QueryFromModel) { | 344 if (!m_redland.isOK()) { |
319 if (!m_redland) { | 345 cerr << "ERROR: SimpleSPARQLQuery::execute: Failed to initialise Redland datastore" << endl; |
320 // There can be no results, because no sources have been | 346 return list; |
321 // added to the model yet (m_redland is only created when | |
322 // addSourceToModel is called) | |
323 cerr << "SimpleSPARQLQuery::execute: NOTE: No sources have been added to data model yet, so no results are possible" << endl; | |
324 return list; | |
325 } | |
326 } | |
327 | |
328 if (m_type == QueryFromSingleSource) { | |
329 #ifdef USE_NEW_RASQAL_API | |
330 if (!m_rasqal) { | |
331 m_rasqal = new WrasqalWorldWrapper(); | |
332 if (!m_rasqal->isOK()) { | |
333 cerr << "ERROR: SimpleSPARQLQuery::execute: Failed to initialise Rasqal query engine" << endl; | |
334 delete m_rasqal; | |
335 m_rasqal = 0; | |
336 return list; | |
337 } | |
338 } | |
339 #else | |
340 if (!m_rasqalInitialised) { | |
341 rasqal_init(); | |
342 m_rasqalInitialised = true; | |
343 } | |
344 #endif | |
345 } | 347 } |
346 | 348 |
347 if (m_type == QueryFromSingleSource) { | 349 if (m_type == QueryFromSingleSource) { |
348 return executeDirectParser(); | 350 return executeDirectParser(); |
349 } else { | 351 } else { |
350 return executeDatastore(); | 352 return executeDatastore(); |
351 } | 353 } |
354 | |
355 #ifdef DEBUG_SIMPLE_SPARQL_QUERY | |
356 if (m_errorString != "") { | |
357 std::cerr << "SimpleSPARQLQuery::execute: error returned: \"" | |
358 << m_errorString.toStdString() << "\"" << std::endl; | |
359 } | |
360 #endif | |
352 } | 361 } |
353 | 362 |
354 SimpleSPARQLQuery::ResultList | 363 SimpleSPARQLQuery::ResultList |
355 SimpleSPARQLQuery::Impl::executeDirectParser() | 364 SimpleSPARQLQuery::Impl::executeDirectParser() |
356 { | 365 { |
366 #ifdef DEBUG_SIMPLE_SPARQL_QUERY | |
367 std::cerr << "SimpleSPARQLQuery::executeDirectParser: Query is: \"" << m_query.toStdString() << "\"" << std::endl; | |
368 #endif | |
369 | |
357 ResultList list; | 370 ResultList list; |
358 | 371 |
359 Profiler profiler("SimpleSPARQLQuery::executeDirectParser"); | 372 Profiler profiler("SimpleSPARQLQuery::executeDirectParser"); |
360 | 373 |
361 #ifdef USE_NEW_RASQAL_API | 374 static QRegExp fromRE("from\\s+<([^>]+)>", Qt::CaseInsensitive); |
362 rasqal_query *query = rasqal_new_query(m_rasqal->getWorld(), "sparql", NULL); | 375 QString fromUri; |
363 #else | 376 |
364 rasqal_query *query = rasqal_new_query("sparql", NULL); | 377 if (fromRE.indexIn(m_query) < 0) { |
378 std::cerr << "SimpleSPARQLQuery::executeDirectParser: Query contains no FROM clause, nothing to parse from" << std::endl; | |
379 return list; | |
380 } else { | |
381 fromUri = fromRE.cap(1); | |
382 #ifdef DEBUG_SIMPLE_SPARQL_QUERY | |
383 std::cerr << "SimpleSPARQLQuery::executeDirectParser: FROM URI is <" | |
384 << fromUri.toStdString() << ">" << std::endl; | |
365 #endif | 385 #endif |
386 } | |
387 | |
388 return executeFor(fromUri); | |
389 } | |
390 | |
391 SimpleSPARQLQuery::ResultList | |
392 SimpleSPARQLQuery::Impl::executeDatastore() | |
393 { | |
394 #ifdef DEBUG_SIMPLE_SPARQL_QUERY | |
395 std::cerr << "SimpleSPARQLQuery::executeDatastore: Query is: \"" << m_query.toStdString() << "\"" << std::endl; | |
396 #endif | |
397 | |
398 ResultList list; | |
399 | |
400 Profiler profiler("SimpleSPARQLQuery::executeDatastore"); | |
401 | |
402 return executeFor(""); | |
403 } | |
404 | |
405 SimpleSPARQLQuery::ResultList | |
406 SimpleSPARQLQuery::Impl::executeFor(QString modelUri) | |
407 { | |
408 ResultList list; | |
409 librdf_query *query; | |
410 | |
411 static std::map<QString, int> counter; | |
412 if (counter.find(m_query) == counter.end()) counter[m_query] = 1; | |
413 else ++counter[m_query]; | |
414 std::cerr << "Counter for this query: " << counter[m_query] << std::endl; | |
415 std::cerr << "Base URI is: \"" << modelUri.toStdString() << "\"" << std::endl; | |
416 | |
417 { | |
418 Profiler p("SimpleSPARQLQuery: Prepare LIBRDF query"); | |
419 query = librdf_new_query | |
420 (m_redland.getWorld(), "sparql", NULL, | |
421 (const unsigned char *)m_query.toUtf8().data(), NULL); | |
422 } | |
423 | |
366 if (!query) { | 424 if (!query) { |
367 m_errorString = "Failed to construct query"; | 425 m_errorString = "Failed to construct query"; |
368 cerr << "SimpleSPARQLQuery: ERROR: " << m_errorString.toStdString() << endl; | |
369 return list; | 426 return list; |
370 } | 427 } |
371 | 428 |
372 rasqal_query_set_error_handler(query, this, errorHandler); | 429 librdf_query_results *results; |
373 rasqal_query_set_fatal_error_handler(query, this, errorHandler); | |
374 | |
375 { | 430 { |
376 Profiler p("SimpleSPARQLQuery: Prepare RASQAL query"); | 431 Profiler p("SimpleSPARQLQuery: Execute LIBRDF query"); |
377 | 432 results = librdf_query_execute(query, m_redland.getModel(modelUri)); |
378 if (rasqal_query_prepare | 433 } |
379 (query, (const unsigned char *)m_query.toUtf8().data(), NULL)) { | |
380 cerr << "SimpleSPARQLQuery: Failed to prepare query" << endl; | |
381 rasqal_free_query(query); | |
382 return list; | |
383 } | |
384 } | |
385 | |
386 rasqal_query_results *results; | |
387 | |
388 { | |
389 Profiler p("SimpleSPARQLQuery: Execute RASQAL query"); | |
390 results = rasqal_query_execute(query); | |
391 } | |
392 | |
393 // cerr << "Query executed" << endl; | |
394 | 434 |
395 if (!results) { | 435 if (!results) { |
396 cerr << "SimpleSPARQLQuery: RASQAL query failed" << endl; | 436 cerr << "SimpleSPARQLQuery: LIBRDF query failed" << endl; |
397 rasqal_free_query(query); | 437 librdf_free_query(query); |
398 return list; | 438 return list; |
399 } | 439 } |
400 | 440 |
401 if (!rasqal_query_results_is_bindings(results)) { | 441 if (!librdf_query_results_is_bindings(results)) { |
402 cerr << "SimpleSPARQLQuery: RASQAL query has wrong result type (not bindings)" << endl; | 442 cerr << "SimpleSPARQLQuery: LIBRDF query has wrong result type (not bindings)" << endl; |
403 rasqal_free_query_results(results); | 443 librdf_free_query_results(results); |
404 rasqal_free_query(query); | 444 librdf_free_query(query); |
405 return list; | 445 return list; |
406 } | 446 } |
407 | 447 |
408 int resultCount = 0; | 448 int resultCount = 0; |
409 int resultTotal = rasqal_query_results_get_count(results); // probably wrong | 449 int resultTotal = librdf_query_results_get_count(results); // probably wrong |
410 m_cancelled = false; | 450 m_cancelled = false; |
411 | 451 |
412 while (!rasqal_query_results_finished(results)) { | 452 while (!librdf_query_results_finished(results)) { |
413 | 453 |
414 int count = rasqal_query_results_get_bindings_count(results); | 454 int count = librdf_query_results_get_bindings_count(results); |
415 | 455 |
416 KeyValueMap resultmap; | 456 KeyValueMap resultmap; |
417 | 457 |
418 for (int i = 0; i < count; ++i) { | 458 for (int i = 0; i < count; ++i) { |
419 | 459 |
420 const unsigned char *name = | 460 const char *name = |
421 rasqal_query_results_get_binding_name(results, i); | 461 librdf_query_results_get_binding_name(results, i); |
422 | 462 |
423 if (!name) { | 463 if (!name) { |
424 std::cerr << "WARNING: Result " << i << " of query has no name" << std::endl; | 464 std::cerr << "WARNING: Result " << i << " of query has no name" << std::endl; |
425 continue; | 465 continue; |
426 } | 466 } |
427 | 467 |
428 rasqal_literal *literal = | 468 librdf_node *node = |
429 rasqal_query_results_get_binding_value(results, i); | 469 librdf_query_results_get_binding_value(results, i); |
430 | 470 |
431 QString key = (const char *)name; | 471 QString key = (const char *)name; |
432 | 472 |
433 if (!literal) { | 473 if (!node) { |
474 #ifdef DEBUG_SIMPLE_SPARQL_QUERY | |
475 std::cerr << i << ". " << key.toStdString() << " -> (nil)" << std::endl; | |
476 #endif | |
434 resultmap[key] = Value(); | 477 resultmap[key] = Value(); |
435 continue; | 478 continue; |
436 } | 479 } |
437 | 480 |
438 ValueType type = LiteralValue; | 481 ValueType type = LiteralValue; |
439 if (literal->type == RASQAL_LITERAL_BLANK) type = BlankValue; | |
440 else if (literal->type == RASQAL_LITERAL_URI) type = URIValue; | |
441 | |
442 QString text; | 482 QString text; |
443 const char *lit = (const char *)rasqal_literal_as_string(literal); | 483 |
444 if (!lit) { | 484 if (librdf_node_is_resource(node)) { |
445 std::cerr << "WARNING: Result " << i << " of query has null value" << std::endl; | 485 |
486 type = URIValue; | |
487 librdf_uri *uri = librdf_node_get_uri(node); | |
488 const char *us = (const char *)librdf_uri_as_string(uri); | |
489 | |
490 if (!us) { | |
491 std::cerr << "WARNING: Result " << i << " of query claims URI type, but has null URI" << std::endl; | |
492 } else { | |
493 text = us; | |
494 } | |
495 | |
496 } else if (librdf_node_is_literal(node)) { | |
497 | |
498 type = LiteralValue; | |
499 | |
500 const char *lit = (const char *)librdf_node_get_literal_value(node); | |
501 if (!lit) { | |
502 std::cerr << "WARNING: Result " << i << " of query claims literal type, but has no literal" << std::endl; | |
503 } else { | |
504 text = lit; | |
505 } | |
506 | |
507 } else if (librdf_node_is_blank(node)) { | |
508 | |
509 type = BlankValue; | |
510 | |
446 } else { | 511 } else { |
447 text = lit; | 512 |
513 cerr << "SimpleSPARQLQuery: LIBRDF query returned unknown node type (not resource, literal, or blank)" << endl; | |
448 } | 514 } |
449 | 515 |
450 #ifdef DEBUG_SIMPLE_SPARQL_QUERY | 516 #ifdef DEBUG_SIMPLE_SPARQL_QUERY |
451 std::cerr << i << ". " << key.toStdString() << " -> " << text.toStdString() << " (type " << type << ")" << std::endl; | 517 cerr << i << ". " << key.toStdString() << " -> " << text.toStdString() << " (type " << type << ")" << endl; |
452 #endif | 518 #endif |
453 | 519 |
454 resultmap[key] = Value(type, text); | 520 resultmap[key] = Value(type, text); |
521 | |
522 // librdf_free_node(node); | |
455 } | 523 } |
456 | 524 |
457 list.push_back(resultmap); | 525 list.push_back(resultmap); |
458 | 526 |
459 rasqal_query_results_next(results); | 527 librdf_query_results_next(results); |
460 | 528 |
461 resultCount++; | 529 resultCount++; |
462 | 530 |
463 if (m_reporter) { | 531 if (m_reporter) { |
464 if (resultCount >= resultTotal) { | 532 if (resultCount >= resultTotal) { |
473 break; | 541 break; |
474 } | 542 } |
475 } | 543 } |
476 } | 544 } |
477 | 545 |
478 rasqal_free_query_results(results); | |
479 rasqal_free_query(query); | |
480 | |
481 return list; | |
482 } | |
483 | |
484 SimpleSPARQLQuery::ResultList | |
485 SimpleSPARQLQuery::Impl::executeDatastore() | |
486 { | |
487 ResultList list; | |
488 | |
489 Profiler profiler("SimpleSPARQLQuery::executeDatastore"); | |
490 | |
491 /*!!! | |
492 static std::map<QString, int> counter; | |
493 if (counter.find(m_query) == counter.end()) counter[m_query] = 1; | |
494 else ++counter[m_query]; | |
495 std::cerr << "Counter for this query: " << counter[m_query] << std::endl; | |
496 std::cerr << "Base URI is: \"" << m_fromUri.toStdString() << "\"" << std::endl; | |
497 */ | |
498 | |
499 librdf_query *query; | |
500 | |
501 { | |
502 Profiler p("SimpleSPARQLQuery: Prepare LIBRDF query"); | |
503 query = librdf_new_query | |
504 (m_redland->getWorld(), "sparql", NULL, | |
505 (const unsigned char *)m_query.toUtf8().data(), NULL); | |
506 } | |
507 | |
508 if (!query) { | |
509 m_errorString = "Failed to construct query"; | |
510 return list; | |
511 } | |
512 | |
513 librdf_query_results *results; | |
514 { | |
515 Profiler p("SimpleSPARQLQuery: Execute LIBRDF query"); | |
516 results = librdf_query_execute(query, m_redland->getModel()); | |
517 } | |
518 | |
519 if (!results) { | |
520 cerr << "SimpleSPARQLQuery: LIBRDF query failed" << endl; | |
521 librdf_free_query(query); | |
522 return list; | |
523 } | |
524 | |
525 if (!librdf_query_results_is_bindings(results)) { | |
526 cerr << "SimpleSPARQLQuery: LIBRDF query has wrong result type (not bindings)" << endl; | |
527 librdf_free_query_results(results); | |
528 librdf_free_query(query); | |
529 return list; | |
530 } | |
531 | |
532 int resultCount = 0; | |
533 int resultTotal = librdf_query_results_get_count(results); // probably wrong | |
534 m_cancelled = false; | |
535 | |
536 while (!librdf_query_results_finished(results)) { | |
537 | |
538 int count = librdf_query_results_get_bindings_count(results); | |
539 | |
540 KeyValueMap resultmap; | |
541 | |
542 for (int i = 0; i < count; ++i) { | |
543 | |
544 const char *name = | |
545 librdf_query_results_get_binding_name(results, i); | |
546 | |
547 if (!name) { | |
548 std::cerr << "WARNING: Result " << i << " of query has no name" << std::endl; | |
549 continue; | |
550 } | |
551 | |
552 librdf_node *node = | |
553 librdf_query_results_get_binding_value(results, i); | |
554 | |
555 QString key = (const char *)name; | |
556 | |
557 if (!node) { | |
558 resultmap[key] = Value(); | |
559 continue; | |
560 } | |
561 | |
562 ValueType type = LiteralValue; | |
563 QString text; | |
564 | |
565 if (librdf_node_is_resource(node)) { | |
566 | |
567 type = URIValue; | |
568 librdf_uri *uri = librdf_node_get_uri(node); | |
569 const char *us = (const char *)librdf_uri_as_string(uri); | |
570 | |
571 if (!us) { | |
572 std::cerr << "WARNING: Result " << i << " of query claims URI type, but has null URI" << std::endl; | |
573 } else { | |
574 text = us; | |
575 } | |
576 | |
577 } else if (librdf_node_is_literal(node)) { | |
578 | |
579 type = LiteralValue; | |
580 | |
581 const char *lit = (const char *)librdf_node_get_literal_value(node); | |
582 if (!lit) { | |
583 std::cerr << "WARNING: Result " << i << " of query claims literal type, but has no literal" << std::endl; | |
584 } else { | |
585 text = lit; | |
586 } | |
587 | |
588 } else if (librdf_node_is_blank(node)) { | |
589 | |
590 type = BlankValue; | |
591 | |
592 } else { | |
593 | |
594 cerr << "SimpleSPARQLQuery: LIBRDF query returned unknown node type (not resource, literal, or blank)" << endl; | |
595 } | |
596 | |
597 #ifdef DEBUG_SIMPLE_SPARQL_QUERY | |
598 cerr << i << ". " << key.toStdString() << " -> " << text.toStdString() << " (type " << type << ")" << endl; | |
599 #endif | |
600 | |
601 resultmap[key] = Value(type, text); | |
602 | |
603 librdf_free_node(node); | |
604 } | |
605 | |
606 list.push_back(resultmap); | |
607 | |
608 librdf_query_results_next(results); | |
609 | |
610 resultCount++; | |
611 | |
612 if (m_reporter) { | |
613 if (resultCount >= resultTotal) { | |
614 if (m_reporter->isDefinite()) m_reporter->setDefinite(false); | |
615 m_reporter->setProgress(resultCount); | |
616 } else { | |
617 m_reporter->setProgress((resultCount * 100) / resultTotal); | |
618 } | |
619 | |
620 if (m_reporter->wasCancelled()) { | |
621 m_cancelled = true; | |
622 break; | |
623 } | |
624 } | |
625 } | |
626 | |
627 librdf_free_query_results(results); | 546 librdf_free_query_results(results); |
628 librdf_free_query(query); | 547 librdf_free_query(query); |
629 | 548 |
630 #ifdef DEBUG_SIMPLE_SPARQL_QUERY | 549 #ifdef DEBUG_SIMPLE_SPARQL_QUERY |
631 cerr << "All results retrieved (" << resultCount << " of them)" << endl; | 550 cerr << "SimpleSPARQLQuery::executeDatastore: All results retrieved (" << resultCount << " of them)" << endl; |
632 #endif | 551 #endif |
633 | 552 |
634 return list; | 553 return list; |
635 } | 554 } |
636 | 555 |
639 { | 558 { |
640 QString err; | 559 QString err; |
641 | 560 |
642 QMutexLocker locker(&m_mutex); | 561 QMutexLocker locker(&m_mutex); |
643 | 562 |
644 if (!m_redland) { | 563 if (!m_redland.isOK()) { |
645 m_redland = new WredlandWorldWrapper(); | 564 std::cerr << "SimpleSPARQLQuery::addSourceToModel: Failed to initialise Redland datastore" << std::endl; |
646 if (!m_redland->isOK()) { | 565 return false; |
647 cerr << "ERROR: SimpleSPARQLQuery::addSourceToModel: Failed to initialise Redland datastore" << endl; | 566 } |
648 delete m_redland; | 567 |
649 m_redland = 0; | 568 if (!m_redland.loadUriIntoDefaultModel(sourceUri, err)) { |
650 return false; | |
651 } | |
652 } | |
653 | |
654 librdf_uri *uri = m_redland->getUri(sourceUri, err); | |
655 | |
656 if (!uri) { | |
657 std::cerr << "SimpleSPARQLQuery::addSourceToModel: Failed to add source URI \"" << sourceUri.toStdString() << ": " << err.toStdString() << std::endl; | 569 std::cerr << "SimpleSPARQLQuery::addSourceToModel: Failed to add source URI \"" << sourceUri.toStdString() << ": " << err.toStdString() << std::endl; |
658 return false; | 570 return false; |
659 } | 571 } |
660 return true; | 572 return true; |
573 } | |
574 | |
575 void | |
576 SimpleSPARQLQuery::Impl::closeSingleSource(QString sourceUri) | |
577 { | |
578 QMutexLocker locker(&m_mutex); | |
579 | |
580 m_redland.freeModel(sourceUri); | |
661 } | 581 } |
662 | 582 |
663 SimpleSPARQLQuery::Value | 583 SimpleSPARQLQuery::Value |
664 SimpleSPARQLQuery::singleResultQuery(QueryType type, | 584 SimpleSPARQLQuery::singleResultQuery(QueryType type, |
665 QString query, QString binding) | 585 QString query, QString binding) |