Changeset View
Changeset View
Standalone View
Standalone View
src/plugins/reports/KexiDBReportDataSource.cpp
1 | /* | 1 | /* | ||
---|---|---|---|---|---|
2 | * Kexi Report Plugin | 2 | * Kexi Report Plugin | ||
3 | * Copyright (C) 2007-2017 by Adam Pigg <adam@piggz.co.uk> | 3 | * Copyright (C) 2007-2017 by Adam Pigg <adam@piggz.co.uk> | ||
4 | * Copyright (C) 2017 Jarosław Staniek <staniek@kde.org> | ||||
4 | * | 5 | * | ||
5 | * This library is free software; you can redistribute it and/or | 6 | * This library is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU Lesser General Public | 7 | * modify it under the terms of the GNU Lesser General Public | ||
7 | * License as published by the Free Software Foundation; either | 8 | * License as published by the Free Software Foundation; either | ||
8 | * version 2.1 of the License, or (at your option) any later version. | 9 | * version 2.1 of the License, or (at your option) any later version. | ||
9 | * | 10 | * | ||
10 | * This library is distributed in the hope that it will be useful, | 11 | * This library is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * Lesser General Public License for more details. | 14 | * Lesser General Public License for more details. | ||
14 | * | 15 | * | ||
15 | * You should have received a copy of the GNU Lesser General Public | 16 | * You should have received a copy of the GNU Lesser General Public | ||
16 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. | 17 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | 18 | */ | ||
18 | 19 | | |||
19 | #include "KexiDBReportDataSource.h" | 20 | #include "KexiDBReportDataSource.h" | ||
20 | #include <core/kexipart.h> | 21 | #include "kexireportpart.h" | ||
21 | 22 | | |||
22 | #include <KDbConnection> | 23 | #include <KDbConnection> | ||
23 | #include <KDbOrderByColumn> | 24 | #include <KDbOrderByColumn> | ||
24 | #include <KDbQuerySchema> | 25 | #include <KDbQuerySchema> | ||
25 | #include <KDbNativeStatementBuilder> | 26 | #include <KDbNativeStatementBuilder> | ||
26 | 27 | | |||
27 | #include <QDomDocument> | 28 | #include <QDomDocument> | ||
28 | #include <QDebug> | 29 | #include <QDebug> | ||
29 | 30 | | |||
30 | class Q_DECL_HIDDEN KexiDBReportDataSource::Private | 31 | class Q_DECL_HIDDEN KexiDBReportDataSource::Private | ||
31 | { | 32 | { | ||
32 | public: | 33 | public: | ||
33 | explicit Private(KDbConnection *pDb) | 34 | explicit Private(KexiReportPartTempData *data) | ||
34 | : cursor(0), connection(pDb), originalSchema(0), copySchema(0) | 35 | : cursor(0), tempData(data), originalSchema(0), copySchema(0) | ||
35 | { | 36 | { | ||
36 | } | 37 | } | ||
37 | ~Private() | 38 | ~Private() | ||
38 | { | 39 | { | ||
39 | delete copySchema; | 40 | delete copySchema; | ||
40 | delete originalSchema; | 41 | delete originalSchema; | ||
41 | } | 42 | } | ||
42 | 43 | | |||
43 | 44 | | |||
44 | QString objectName; | 45 | QString objectName; | ||
45 | 46 | | |||
46 | KDbCursor *cursor; | 47 | KDbCursor *cursor; | ||
47 | KDbConnection *connection; | 48 | KexiReportPartTempData *tempData; | ||
48 | KDbQuerySchema *originalSchema; | 49 | KDbQuerySchema *originalSchema; | ||
49 | KDbQuerySchema *copySchema; | 50 | KDbQuerySchema *copySchema; | ||
50 | }; | 51 | }; | ||
51 | 52 | | |||
52 | KexiDBReportDataSource::KexiDBReportDataSource(const QString& objectName, | 53 | KexiDBReportDataSource::KexiDBReportDataSource(const QString &objectName, const QString &pluginId, | ||
53 | const QString& pluginId, | 54 | KexiReportPartTempData *data) | ||
54 | KDbConnection* pDb) | 55 | : d(new Private(data)) | ||
55 | : d(new Private(pDb)) | | |||
56 | { | 56 | { | ||
57 | d->objectName = objectName; | 57 | d->objectName = objectName; | ||
58 | getSchema(pluginId); | 58 | getSchema(pluginId); | ||
59 | } | 59 | } | ||
60 | 60 | | |||
61 | void KexiDBReportDataSource::setSorting(const QList<SortedField>& sorting) | 61 | void KexiDBReportDataSource::setSorting(const QList<SortedField>& sorting) | ||
62 | { | 62 | { | ||
63 | if (d->copySchema) { | 63 | if (d->copySchema) { | ||
64 | if (sorting.isEmpty()) | 64 | if (sorting.isEmpty()) | ||
65 | return; | 65 | return; | ||
66 | KDbOrderByColumnList order; | 66 | KDbOrderByColumnList order; | ||
67 | for (int i = 0; i < sorting.count(); i++) { | 67 | for (int i = 0; i < sorting.count(); i++) { | ||
68 | if (!order.appendField(d->connection, d->copySchema, sorting[i].field(), | 68 | if (!order.appendField(d->tempData->connection(), d->copySchema, sorting[i].field(), | ||
69 | KDbOrderByColumn::fromQt(sorting[i].order()))) | 69 | KDbOrderByColumn::fromQt(sorting[i].order()))) | ||
70 | { | 70 | { | ||
71 | qWarning() << "Cannot set sort field" << i << sorting[i].field(); | 71 | qWarning() << "Cannot set sort field" << i << sorting[i].field(); | ||
72 | return; | 72 | return; | ||
73 | } | 73 | } | ||
74 | } | 74 | } | ||
75 | d->copySchema->setOrderByColumnList(order); | 75 | d->copySchema->setOrderByColumnList(order); | ||
76 | } else { | 76 | } else { | ||
Show All 29 Lines | |||||
106 | KexiDBReportDataSource::~KexiDBReportDataSource() | 106 | KexiDBReportDataSource::~KexiDBReportDataSource() | ||
107 | { | 107 | { | ||
108 | close(); | 108 | close(); | ||
109 | delete d; | 109 | delete d; | ||
110 | } | 110 | } | ||
111 | 111 | | |||
112 | bool KexiDBReportDataSource::open() | 112 | bool KexiDBReportDataSource::open() | ||
113 | { | 113 | { | ||
114 | if ( d->connection && d->cursor == 0 ) | 114 | if ( d->tempData->connection() && d->cursor == 0 ) | ||
115 | { | 115 | { | ||
116 | if ( d->objectName.isEmpty() ) | 116 | if ( d->objectName.isEmpty() ) | ||
117 | { | 117 | { | ||
118 | return false; | 118 | return false; | ||
119 | } | 119 | } | ||
120 | else if ( d->copySchema) | 120 | else if ( d->copySchema) | ||
121 | { | 121 | { | ||
122 | qDebug() << "Opening cursor.." | 122 | qDebug() << "Opening cursor.." | ||
123 | << KDbConnectionAndQuerySchema(d->connection, *d->copySchema); | 123 | << KDbConnectionAndQuerySchema(d->tempData->connection(), *d->copySchema); | ||
124 | d->cursor = d->connection->executeQuery(d->copySchema, KDbCursor::Option::Buffered); | 124 | d->cursor = d->tempData->connection()->executeQuery(d->copySchema, KDbCursor::Option::Buffered); | ||
125 | } | 125 | } | ||
126 | 126 | | |||
127 | 127 | | |||
128 | if ( d->cursor ) | 128 | if ( d->cursor ) | ||
129 | { | 129 | { | ||
130 | qDebug() << "Moving to first record.."; | 130 | qDebug() << "Moving to first record.."; | ||
131 | return d->cursor->moveFirst(); | 131 | return d->cursor->moveFirst(); | ||
132 | } | 132 | } | ||
133 | else | 133 | else | ||
134 | return false; | 134 | return false; | ||
135 | } | 135 | } | ||
136 | return false; | 136 | return false; | ||
137 | } | 137 | } | ||
138 | 138 | | |||
139 | bool KexiDBReportDataSource::close() | 139 | bool KexiDBReportDataSource::close() | ||
140 | { | 140 | { | ||
141 | if (d->cursor) { | 141 | if (d->cursor) { | ||
142 | const bool ok = d->cursor->close(); | 142 | const bool ok = d->cursor->close(); | ||
143 | d->connection->deleteCursor(d->cursor); | 143 | d->tempData->connection()->deleteCursor(d->cursor); | ||
144 | d->cursor = nullptr; | 144 | d->cursor = nullptr; | ||
145 | return ok; | 145 | return ok; | ||
146 | } | 146 | } | ||
147 | return true; | 147 | return true; | ||
148 | } | 148 | } | ||
149 | 149 | | |||
150 | bool KexiDBReportDataSource::getSchema(const QString& pluginId) | 150 | bool KexiDBReportDataSource::getSchema(const QString& pluginId) | ||
151 | { | 151 | { | ||
152 | if (d->connection) | 152 | if (d->tempData->connection()) { | ||
153 | { | 153 | KDbTableSchemaChangeListener::unregisterForChanges(d->tempData->connection(), d->tempData); | ||
154 | delete d->originalSchema; | 154 | delete d->originalSchema; | ||
155 | d->originalSchema = 0; | 155 | d->originalSchema = 0; | ||
156 | delete d->copySchema; | 156 | delete d->copySchema; | ||
157 | d->copySchema = 0; | 157 | d->copySchema = 0; | ||
158 | 158 | | |||
159 | KDbTableSchema *table = nullptr; | ||||
160 | KDbQuerySchema *query = nullptr; | ||||
159 | if ((pluginId.isEmpty() || pluginId == "org.kexi-project.table") | 161 | if ((pluginId.isEmpty() || pluginId == "org.kexi-project.table") | ||
160 | && d->connection->tableSchema(d->objectName)) | 162 | && (table = d->tempData->connection()->tableSchema(d->objectName))) | ||
161 | { | 163 | { | ||
162 | qDebug() << d->objectName << "is a table.."; | 164 | qDebug() << d->objectName << "is a table.."; | ||
163 | d->originalSchema = new KDbQuerySchema(d->connection->tableSchema(d->objectName)); | 165 | d->originalSchema = new KDbQuerySchema(table); | ||
164 | } | 166 | } | ||
165 | else if ((pluginId.isEmpty() || pluginId == "org.kexi-project.query") | 167 | else if ((pluginId.isEmpty() || pluginId == "org.kexi-project.query") | ||
166 | && d->connection->querySchema(d->objectName)) | 168 | && (query = d->tempData->connection()->querySchema(d->objectName))) | ||
167 | { | 169 | { | ||
168 | qDebug() << d->objectName << "is a query.."; | 170 | qDebug() << d->objectName << "is a query.."; | ||
169 | qDebug() << KDbConnectionAndQuerySchema(d->connection, | 171 | qDebug() << KDbConnectionAndQuerySchema(d->tempData->connection(), *query); | ||
170 | *d->connection->querySchema(d->objectName)); | 172 | d->originalSchema = new KDbQuerySchema(*query, d->tempData->connection()); | ||
171 | d->originalSchema | | |||
172 | = new KDbQuerySchema(*(d->connection->querySchema(d->objectName)), d->connection); | | |||
173 | } | 173 | } | ||
174 | 174 | | |||
175 | if (d->originalSchema) { | 175 | if (d->originalSchema) { | ||
176 | const KDbNativeStatementBuilder builder(d->connection, KDb::DriverEscaping); | 176 | const KDbNativeStatementBuilder builder(d->tempData->connection(), KDb::DriverEscaping); | ||
177 | KDbEscapedString sql; | 177 | KDbEscapedString sql; | ||
178 | if (builder.generateSelectStatement(&sql, d->originalSchema)) { | 178 | if (builder.generateSelectStatement(&sql, d->originalSchema)) { | ||
179 | qDebug() << "Original:" << sql; | 179 | qDebug() << "Original:" << sql; | ||
180 | } else { | 180 | } else { | ||
181 | qDebug() << "Original: ERROR"; | 181 | qDebug() << "Original: ERROR"; | ||
182 | return false; | ||||
182 | } | 183 | } | ||
183 | qDebug() << KDbConnectionAndQuerySchema(d->connection, *d->originalSchema); | 184 | qDebug() << KDbConnectionAndQuerySchema(d->tempData->connection(), *d->originalSchema); | ||
184 | 185 | | |||
185 | d->copySchema = new KDbQuerySchema(*d->originalSchema, d->connection); | 186 | d->copySchema = new KDbQuerySchema(*d->originalSchema, d->tempData->connection()); | ||
186 | qDebug() << KDbConnectionAndQuerySchema(d->connection, *d->copySchema); | 187 | qDebug() << KDbConnectionAndQuerySchema(d->tempData->connection(), *d->copySchema); | ||
187 | if (builder.generateSelectStatement(&sql, d->copySchema)) { | 188 | if (builder.generateSelectStatement(&sql, d->copySchema)) { | ||
188 | qDebug() << "Copy:" << sql; | 189 | qDebug() << "Copy:" << sql; | ||
189 | } else { | 190 | } else { | ||
190 | qDebug() << "Copy: ERROR"; | 191 | qDebug() << "Copy: ERROR"; | ||
192 | return false; | ||||
193 | } | ||||
194 | if (table) { | ||||
195 | KDbTableSchemaChangeListener::registerForChanges(d->tempData->connection(), d->tempData, table); | ||||
196 | } else if (query) { | ||||
197 | KDbTableSchemaChangeListener::registerForChanges(d->tempData->connection(), d->tempData, query); | ||||
191 | } | 198 | } | ||
192 | } | 199 | } | ||
193 | return true; | 200 | return true; | ||
194 | } | 201 | } | ||
195 | return false; | 202 | return false; | ||
196 | } | 203 | } | ||
197 | 204 | | |||
198 | QString KexiDBReportDataSource::sourceName() const | 205 | QString KexiDBReportDataSource::sourceName() const | ||
199 | { | 206 | { | ||
200 | return d->objectName; | 207 | return d->objectName; | ||
201 | } | 208 | } | ||
202 | 209 | | |||
203 | int KexiDBReportDataSource::fieldNumber ( const QString &fld ) const | 210 | int KexiDBReportDataSource::fieldNumber ( const QString &fld ) const | ||
204 | { | 211 | { | ||
205 | if (!d->cursor || !d->cursor->query()) { | 212 | if (!d->cursor || !d->cursor->query()) { | ||
206 | return -1; | 213 | return -1; | ||
207 | } | 214 | } | ||
208 | const KDbQueryColumnInfo::Vector fieldsExpanded(d->cursor->query()->fieldsExpanded( | 215 | const KDbQueryColumnInfo::Vector fieldsExpanded(d->cursor->query()->fieldsExpanded( | ||
209 | d->connection, KDbQuerySchema::FieldsExpandedMode::Unique)); | 216 | d->tempData->connection(), KDbQuerySchema::FieldsExpandedMode::Unique)); | ||
210 | for (int i = 0; i < fieldsExpanded.size(); ++i) { | 217 | for (int i = 0; i < fieldsExpanded.size(); ++i) { | ||
211 | if (0 == QString::compare(fld, fieldsExpanded[i]->aliasOrName(), Qt::CaseInsensitive)) { | 218 | if (0 == QString::compare(fld, fieldsExpanded[i]->aliasOrName(), Qt::CaseInsensitive)) { | ||
212 | return i; | 219 | return i; | ||
213 | } | 220 | } | ||
214 | } | 221 | } | ||
215 | return -1; | 222 | return -1; | ||
216 | } | 223 | } | ||
217 | 224 | | |||
218 | QStringList KexiDBReportDataSource::fieldNames() const | 225 | QStringList KexiDBReportDataSource::fieldNames() const | ||
219 | { | 226 | { | ||
220 | if (!d->originalSchema) { | 227 | if (!d->originalSchema) { | ||
221 | return QStringList(); | 228 | return QStringList(); | ||
222 | } | 229 | } | ||
223 | QStringList names; | 230 | QStringList names; | ||
224 | const KDbQueryColumnInfo::Vector fieldsExpanded(d->originalSchema->fieldsExpanded( | 231 | const KDbQueryColumnInfo::Vector fieldsExpanded(d->originalSchema->fieldsExpanded( | ||
225 | d->connection, KDbQuerySchema::FieldsExpandedMode::Unique)); | 232 | d->tempData->connection(), KDbQuerySchema::FieldsExpandedMode::Unique)); | ||
226 | for (int i = 0; i < fieldsExpanded.size(); i++) { | 233 | for (int i = 0; i < fieldsExpanded.size(); i++) { | ||
227 | //! @todo in some Kexi mode captionOrAliasOrName() would be used here (more user-friendly) | 234 | //! @todo in some Kexi mode captionOrAliasOrName() would be used here (more user-friendly) | ||
228 | names.append(fieldsExpanded[i]->aliasOrName()); | 235 | names.append(fieldsExpanded[i]->aliasOrName()); | ||
229 | } | 236 | } | ||
230 | return names; | 237 | return names; | ||
231 | } | 238 | } | ||
232 | 239 | | |||
233 | QVariant KexiDBReportDataSource::value (int i) const | 240 | QVariant KexiDBReportDataSource::value (int i) const | ||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Line(s) | 290 | if ( d->cursor ) | |||
284 | return d->cursor->at(); | 291 | return d->cursor->at(); | ||
285 | 292 | | |||
286 | return 0; | 293 | return 0; | ||
287 | } | 294 | } | ||
288 | 295 | | |||
289 | qint64 KexiDBReportDataSource::recordCount() const | 296 | qint64 KexiDBReportDataSource::recordCount() const | ||
290 | { | 297 | { | ||
291 | if (d->copySchema) { | 298 | if (d->copySchema) { | ||
292 | return d->connection->recordCount(d->copySchema); | 299 | return d->tempData->connection()->recordCount(d->copySchema); | ||
293 | } | 300 | } | ||
294 | 301 | | |||
295 | return 1; | 302 | return 1; | ||
296 | } | 303 | } | ||
297 | 304 | | |||
298 | QStringList KexiDBReportDataSource::dataSourceNames() const | 305 | QStringList KexiDBReportDataSource::dataSourceNames() const | ||
299 | { | 306 | { | ||
300 | //Get the list of queries in the database | 307 | //Get the list of queries in the database | ||
301 | QStringList qs; | 308 | QStringList qs; | ||
302 | if (d->connection && d->connection->isConnected()) { | 309 | if (d->tempData->connection() && d->tempData->connection()->isConnected()) { | ||
303 | QList<int> tids = d->connection->tableIds(); | 310 | QList<int> tids = d->tempData->connection()->tableIds(); | ||
304 | qs << ""; | 311 | qs << ""; | ||
305 | for (int i = 0; i < tids.size(); ++i) { | 312 | for (int i = 0; i < tids.size(); ++i) { | ||
306 | KDbTableSchema* tsc = d->connection->tableSchema(tids[i]); | 313 | KDbTableSchema* tsc = d->tempData->connection()->tableSchema(tids[i]); | ||
307 | if (tsc) | 314 | if (tsc) | ||
308 | qs << tsc->name(); | 315 | qs << tsc->name(); | ||
309 | } | 316 | } | ||
310 | 317 | | |||
311 | QList<int> qids = d->connection->queryIds(); | 318 | QList<int> qids = d->tempData->connection()->queryIds(); | ||
312 | qs << ""; | 319 | qs << ""; | ||
313 | for (int i = 0; i < qids.size(); ++i) { | 320 | for (int i = 0; i < qids.size(); ++i) { | ||
314 | KDbQuerySchema* qsc = d->connection->querySchema(qids[i]); | 321 | KDbQuerySchema* qsc = d->tempData->connection()->querySchema(qids[i]); | ||
315 | if (qsc) | 322 | if (qsc) | ||
316 | qs << qsc->name(); | 323 | qs << qsc->name(); | ||
317 | } | 324 | } | ||
318 | } | 325 | } | ||
319 | 326 | | |||
320 | return qs; | 327 | return qs; | ||
321 | } | 328 | } | ||
322 | 329 | | |||
323 | KReportDataSource* KexiDBReportDataSource::create(const QString& source) const | 330 | KReportDataSource* KexiDBReportDataSource::create(const QString& source) const | ||
324 | { | 331 | { | ||
325 | return new KexiDBReportDataSource(source, QString(), d->connection); | 332 | return new KexiDBReportDataSource(source, QString(), d->tempData); | ||
326 | } | 333 | } |