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