qsqldriver.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/sql/kernel/qsqldriver.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtSql module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "qsqldriver.h"-
41-
42#include "qdatetime.h"-
43#include "qsqlerror.h"-
44#include "qsqlfield.h"-
45#include "qsqlindex.h"-
46#include "private/qobject_p.h"-
47#include "private/qsqldriver_p.h"-
48-
49QT_BEGIN_NAMESPACE-
50-
51static QString prepareIdentifier(const QString &identifier,-
52 QSqlDriver::IdentifierType type, const QSqlDriver *driver)-
53{-
54 Q_ASSERT( driver != NULL );-
55 QString ret = identifier;-
56 if (!driver->isIdentifierEscaped(identifier, type)) {
!driver->isIde...ntifier, type)Description
TRUEevaluated 1324 times by 4 tests
Evaluated by:
  • tst_QItemModel
  • tst_QSqlDatabase
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
FALSEevaluated 10 times by 1 test
Evaluated by:
  • tst_QSqlRelationalTableModel
10-1324
57 ret = driver->escapeIdentifier(identifier, type);-
58 }
executed 1324 times by 4 tests: end of block
Executed by:
  • tst_QItemModel
  • tst_QSqlDatabase
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
1324
59 return ret;
executed 1334 times by 4 tests: return ret;
Executed by:
  • tst_QItemModel
  • tst_QSqlDatabase
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
1334
60}-
61-
62/*!-
63 \class QSqlDriver-
64 \brief The QSqlDriver class is an abstract base class for accessing-
65 specific SQL databases.-
66-
67 \ingroup database-
68 \inmodule QtSql-
69-
70 This class should not be used directly. Use QSqlDatabase instead.-
71-
72 If you want to create your own SQL drivers, you can subclass this-
73 class and reimplement its pure virtual functions and those-
74 virtual functions that you need. See \l{How to Write Your Own-
75 Database Driver} for more information.-
76-
77 \sa QSqlDatabase, QSqlResult-
78*/-
79-
80/*!-
81 Constructs a new driver with the given \a parent.-
82*/-
83-
84QSqlDriver::QSqlDriver(QObject *parent)-
85 : QObject(*new QSqlDriverPrivate, parent)-
86{-
87}
executed 20 times by 10 tests: end of block
Executed by:
  • tst_QItemModel
  • tst_QSql
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlQuery
  • tst_QSqlQueryModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
  • tst_QSqlThread
  • tst_qsqlresult - unknown status
20
88-
89/*! \internal-
90*/-
91QSqlDriver::QSqlDriver(QSqlDriverPrivate &dd, QObject *parent)-
92 : QObject(dd, parent)-
93{-
94}
executed 32 times by 9 tests: end of block
Executed by:
  • tst_QItemModel
  • tst_QSql
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlQuery
  • tst_QSqlQueryModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
  • tst_QSqlThread
32
95-
96/*!-
97 Destroys the object and frees any allocated resources.-
98*/-
99-
100QSqlDriver::~QSqlDriver()-
101{-
102}-
103-
104/*!-
105 \since 4.4-
106-
107 \fn QSqlDriver::notification(const QString &name)-
108-
109 This signal is emitted when the database posts an event notification-
110 that the driver subscribes to. \a name identifies the event notification.-
111-
112 \sa subscribeToNotification()-
113*/-
114-
115/*!-
116 \since 5.0-
117-
118 \fn QSqlDriver::notification(const QString &name, QSqlDriver::NotificationSource source, const QVariant & payload)-
119-
120 This signal is emitted when the database posts an event notification-
121 that the driver subscribes to. \a name identifies the event notification, \a source indicates the signal source,-
122 \a payload holds the extra data optionally delivered with the notification.-
123-
124 \sa subscribeToNotification()-
125*/-
126-
127/*!-
128 \fn bool QSqlDriver::open(const QString &db, const QString &user, const QString& password,-
129 const QString &host, int port, const QString &options)-
130-
131 Derived classes must reimplement this pure virtual function to-
132 open a database connection on database \a db, using user name \a-
133 user, password \a password, host \a host, port \a port and-
134 connection options \a options.-
135-
136 The function must return true on success and false on failure.-
137-
138 \sa setOpen()-
139*/-
140-
141/*!-
142 \fn bool QSqlDriver::close()-
143-
144 Derived classes must reimplement this pure virtual function in-
145 order to close the database connection. Return true on success,-
146 false on failure.-
147-
148 \sa open(), setOpen()-
149*/-
150-
151/*!-
152 \fn QSqlResult *QSqlDriver::createResult() const-
153-
154 Creates an empty SQL result on the database. Derived classes must-
155 reimplement this function and return a QSqlResult object-
156 appropriate for their database to the caller.-
157*/-
158-
159/*!-
160 Returns \c true if the database connection is open; otherwise returns-
161 false.-
162*/-
163-
164bool QSqlDriver::isOpen() const-
165{-
166 Q_D(const QSqlDriver);-
167 return d->isOpen;
executed 8308 times by 12 tests: return d->isOpen;
Executed by:
  • tst_QItemModel
  • tst_QSql
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlQuery
  • tst_QSqlQueryModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
  • tst_QSqlThread
  • tst_qitemmodel - unknown status
  • tst_qsqldatabase - unknown status
  • tst_qsqltablemodel - unknown status
8308
168}-
169-
170/*!-
171 Returns \c true if the there was an error opening the database-
172 connection; otherwise returns \c false.-
173*/-
174-
175bool QSqlDriver::isOpenError() const-
176{-
177 Q_D(const QSqlDriver);-
178 return d->isOpenError;
executed 5596 times by 9 tests: return d->isOpenError;
Executed by:
  • tst_QItemModel
  • tst_QSql
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlQuery
  • tst_QSqlQueryModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
  • tst_QSqlThread
5596
179}-
180-
181/*!-
182 \enum QSqlDriver::DriverFeature-
183-
184 This enum contains a list of features a driver might support. Use-
185 hasFeature() to query whether a feature is supported or not.-
186-
187 \value Transactions Whether the driver supports SQL transactions.-
188 \value QuerySize Whether the database is capable of reporting the size-
189 of a query. Note that some databases do not support returning the size-
190 (i.e. number of rows returned) of a query, in which case-
191 QSqlQuery::size() will return -1.-
192 \value BLOB Whether the driver supports Binary Large Object fields.-
193 \value Unicode Whether the driver supports Unicode strings if the-
194 database server does.-
195 \value PreparedQueries Whether the driver supports prepared query execution.-
196 \value NamedPlaceholders Whether the driver supports the use of named placeholders.-
197 \value PositionalPlaceholders Whether the driver supports the use of positional placeholders.-
198 \value LastInsertId Whether the driver supports returning the Id of the last touched row.-
199 \value BatchOperations Whether the driver supports batched operations, see QSqlQuery::execBatch()-
200 \value SimpleLocking Whether the driver disallows a write lock on a table while other queries have a read lock on it.-
201 \value LowPrecisionNumbers Whether the driver allows fetching numerical values with low precision.-
202 \value EventNotifications Whether the driver supports database event notifications.-
203 \value FinishQuery Whether the driver can do any low-level resource cleanup when QSqlQuery::finish() is called.-
204 \value MultipleResultSets Whether the driver can access multiple result sets returned from batched statements or stored procedures.-
205 \value CancelQuery Whether the driver allows cancelling a running query.-
206-
207 More information about supported features can be found in the-
208 \l{sql-driver.html}{Qt SQL driver} documentation.-
209-
210 \sa hasFeature()-
211*/-
212-
213/*!-
214 \enum QSqlDriver::StatementType-
215-
216 This enum contains a list of SQL statement (or clause) types the-
217 driver can create.-
218-
219 \value WhereStatement An SQL \c WHERE statement (e.g., \c{WHERE f = 5}).-
220 \value SelectStatement An SQL \c SELECT statement (e.g., \c{SELECT f FROM t}).-
221 \value UpdateStatement An SQL \c UPDATE statement (e.g., \c{UPDATE TABLE t set f = 1}).-
222 \value InsertStatement An SQL \c INSERT statement (e.g., \c{INSERT INTO t (f) values (1)}).-
223 \value DeleteStatement An SQL \c DELETE statement (e.g., \c{DELETE FROM t}).-
224-
225 \sa sqlStatement()-
226*/-
227-
228/*!-
229 \enum QSqlDriver::IdentifierType-
230-
231 This enum contains a list of SQL identifier types.-
232-
233 \value FieldName A SQL field name-
234 \value TableName A SQL table name-
235*/-
236-
237/*!-
238 \enum QSqlDriver::NotificationSource-
239-
240 This enum contains a list of SQL notification sources.-
241-
242 \value UnknownSource The notification source is unknown-
243 \value SelfSource The notification source is this connection-
244 \value OtherSource The notification source is another connection-
245*/-
246-
247/*!-
248 \enum QSqlDriver::DbmsType-
249-
250 This enum contains DBMS types.-
251-
252 \value UnknownDbms-
253 \value MSSqlServer-
254 \value MySqlServer-
255 \value PostgreSQL-
256 \value Oracle-
257 \value Sybase-
258 \value SQLite-
259 \value Interbase-
260 \value DB2-
261*/-
262-
263/*!-
264 \fn bool QSqlDriver::hasFeature(DriverFeature feature) const-
265-
266 Returns \c true if the driver supports feature \a feature; otherwise-
267 returns \c false.-
268-
269 Note that some databases need to be open() before this can be-
270 determined.-
271-
272 \sa DriverFeature-
273*/-
274-
275/*!-
276 This function sets the open state of the database to \a open.-
277 Derived classes can use this function to report the status of-
278 open().-
279-
280 \sa open(), setOpenError()-
281*/-
282-
283void QSqlDriver::setOpen(bool open)-
284{-
285 Q_D(QSqlDriver);-
286 d->isOpen = open;-
287}
executed 89 times by 10 tests: end of block
Executed by:
  • tst_QItemModel
  • tst_QSql
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlQuery
  • tst_QSqlQueryModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
  • tst_QSqlThread
  • tst_qitemmodel - unknown status
89
288-
289/*!-
290 This function sets the open error state of the database to \a-
291 error. Derived classes can use this function to report the status-
292 of open(). Note that if \a error is true the open state of the-
293 database is set to closed (i.e., isOpen() returns \c false).-
294-
295 \sa open(), setOpen()-
296*/-
297-
298void QSqlDriver::setOpenError(bool error)-
299{-
300 Q_D(QSqlDriver);-
301 d->isOpenError = error;-
302 if (error)
errorDescription
TRUEevaluated 3 times by 1 test
Evaluated by:
  • tst_QSqlDatabase
FALSEevaluated 89 times by 10 tests
Evaluated by:
  • tst_QItemModel
  • tst_QSql
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlQuery
  • tst_QSqlQueryModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
  • tst_QSqlThread
  • tst_qitemmodel - unknown status
3-89
303 d->isOpen = false;
executed 3 times by 1 test: d->isOpen = false;
Executed by:
  • tst_QSqlDatabase
3
304}
executed 92 times by 10 tests: end of block
Executed by:
  • tst_QItemModel
  • tst_QSql
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlQuery
  • tst_QSqlQueryModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
  • tst_QSqlThread
  • tst_qitemmodel - unknown status
92
305-
306/*!-
307 This function is called to begin a transaction. If successful,-
308 return true, otherwise return false. The default implementation-
309 does nothing and returns \c false.-
310-
311 \sa commitTransaction(), rollbackTransaction()-
312*/-
313-
314bool QSqlDriver::beginTransaction()-
315{-
316 return false;
never executed: return false;
0
317}-
318-
319/*!-
320 This function is called to commit a transaction. If successful,-
321 return true, otherwise return false. The default implementation-
322 does nothing and returns \c false.-
323-
324 \sa beginTransaction(), rollbackTransaction()-
325*/-
326-
327bool QSqlDriver::commitTransaction()-
328{-
329 return false;
never executed: return false;
0
330}-
331-
332/*!-
333 This function is called to rollback a transaction. If successful,-
334 return true, otherwise return false. The default implementation-
335 does nothing and returns \c false.-
336-
337 \sa beginTransaction(), commitTransaction()-
338*/-
339-
340bool QSqlDriver::rollbackTransaction()-
341{-
342 return false;
never executed: return false;
0
343}-
344-
345/*!-
346 This function is used to set the value of the last error, \a error,-
347 that occurred on the database.-
348-
349 \sa lastError()-
350*/-
351-
352void QSqlDriver::setLastError(const QSqlError &error)-
353{-
354 Q_D(QSqlDriver);-
355 d->error = error;-
356}
executed 37 times by 9 tests: end of block
Executed by:
  • tst_QItemModel
  • tst_QSql
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlQuery
  • tst_QSqlQueryModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
  • tst_QSqlThread
37
357-
358/*!-
359 Returns a QSqlError object which contains information about the-
360 last error that occurred on the database.-
361*/-
362-
363QSqlError QSqlDriver::lastError() const-
364{-
365 Q_D(const QSqlDriver);-
366 return d->error;
executed 29 times by 6 tests: return d->error;
Executed by:
  • tst_QSql
  • tst_QSqlDatabase
  • tst_QSqlQuery
  • tst_QSqlQueryModel
  • tst_QSqlTableModel
  • tst_QSqlThread
29
367}-
368-
369/*!-
370 Returns a list of the names of the tables in the database. The-
371 default implementation returns an empty list.-
372-
373 The \a tableType argument describes what types of tables-
374 should be returned. Due to binary compatibility, the string-
375 contains the value of the enum QSql::TableTypes as text.-
376 An empty string should be treated as QSql::Tables for-
377 backward compatibility.-
378*/-
379-
380QStringList QSqlDriver::tables(QSql::TableType) const-
381{-
382 return QStringList();
executed 1 time by 1 test: return QStringList();
Executed by:
  • tst_QSql
1
383}-
384-
385/*!-
386 Returns the primary index for table \a tableName. Returns an empty-
387 QSqlIndex if the table doesn't have a primary index. The default-
388 implementation returns an empty index.-
389*/-
390-
391QSqlIndex QSqlDriver::primaryIndex(const QString&) const-
392{-
393 return QSqlIndex();
never executed: return QSqlIndex();
0
394}-
395-
396-
397/*!-
398 Returns a QSqlRecord populated with the names of the fields in-
399 table \a tableName. If no such table exists, an empty record is-
400 returned. The default implementation returns an empty record.-
401*/-
402-
403QSqlRecord QSqlDriver::record(const QString & /* tableName */) const-
404{-
405 return QSqlRecord();
never executed: return QSqlRecord();
0
406}-
407-
408/*!-
409 Returns the \a identifier escaped according to the database rules.-
410 \a identifier can either be a table name or field name, dependent-
411 on \a type.-
412-
413 The default implementation does nothing.-
414 \sa isIdentifierEscaped()-
415 */-
416QString QSqlDriver::escapeIdentifier(const QString &identifier, IdentifierType) const-
417{-
418 return identifier;
never executed: return identifier;
0
419}-
420-
421/*!-
422 Returns whether \a identifier is escaped according to the database rules.-
423 \a identifier can either be a table name or field name, dependent-
424 on \a type.-
425-
426 Reimplement this function if you want to provide your own implementation in your-
427 QSqlDriver subclass,-
428-
429 \sa stripDelimiters(), escapeIdentifier()-
430 */-
431bool QSqlDriver::isIdentifierEscaped(const QString &identifier, IdentifierType type) const-
432{-
433 Q_UNUSED(type);-
434 return identifier.size() > 2
executed 2790 times by 8 tests: return identifier.size() > 2 && identifier.startsWith(QLatin1Char('"')) && identifier.endsWith(QLatin1Char('"'));
Executed by:
  • tst_QItemModel
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlQuery
  • tst_QSqlQueryModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
  • tst_QSqlThread
2790
435 && identifier.startsWith(QLatin1Char('"')) //left delimited
executed 2790 times by 8 tests: return identifier.size() > 2 && identifier.startsWith(QLatin1Char('"')) && identifier.endsWith(QLatin1Char('"'));
Executed by:
  • tst_QItemModel
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlQuery
  • tst_QSqlQueryModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
  • tst_QSqlThread
2790
436 && identifier.endsWith(QLatin1Char('"')); //right delimited
executed 2790 times by 8 tests: return identifier.size() > 2 && identifier.startsWith(QLatin1Char('"')) && identifier.endsWith(QLatin1Char('"'));
Executed by:
  • tst_QItemModel
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlQuery
  • tst_QSqlQueryModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
  • tst_QSqlThread
2790
437}-
438-
439/*!-
440 Returns the \a identifier with the leading and trailing delimiters removed,-
441 \a identifier can either be a table name or field name,-
442 dependent on \a type. If \a identifier does not have leading-
443 and trailing delimiter characters, \a identifier is returned without-
444 modification.-
445-
446 Reimplement this function if you want to provide your own implementation in your-
447 QSqlDriver subclass,-
448-
449 \since 4.5-
450 \sa isIdentifierEscaped()-
451 */-
452QString QSqlDriver::stripDelimiters(const QString &identifier, IdentifierType type) const-
453{-
454 QString ret;-
455 if (isIdentifierEscaped(identifier, type)) {
isIdentifierEs...ntifier, type)Description
TRUEevaluated 99 times by 4 tests
Evaluated by:
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
FALSEnever evaluated
0-99
456 ret = identifier.mid(1);-
457 ret.chop(1);-
458 } else {
executed 99 times by 4 tests: end of block
Executed by:
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
99
459 ret = identifier;-
460 }
never executed: end of block
0
461 return ret;
executed 99 times by 4 tests: return ret;
Executed by:
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
99
462}-
463-
464/*!-
465 Returns a SQL statement of type \a type for the table \a tableName-
466 with the values from \a rec. If \a preparedStatement is true, the-
467 string will contain placeholders instead of values.-
468-
469 The generated flag in each field of \a rec determines whether the-
470 field is included in the generated statement.-
471-
472 This method can be used to manipulate tables without having to worry-
473 about database-dependent SQL dialects. For non-prepared statements,-
474 the values will be properly escaped.-
475-
476 In the WHERE statement, each non-null field of \a rec specifies a-
477 filter condition of equality to the field value, or if prepared, a-
478 placeholder. However, prepared or not, a null field specifies the-
479 condition IS NULL and never introduces a placeholder. The-
480 application must not attempt to bind data for the null field during-
481 execution. The field must be set to some non-null value if a-
482 placeholder is desired. Furthermore, since non-null fields specify-
483 equality conditions and SQL NULL is not equal to anything, even-
484 itself, it is generally not useful to bind a null to a placeholder.-
485-
486*/-
487QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName,-
488 const QSqlRecord &rec, bool preparedStatement) const-
489{-
490 int i;-
491 QString s;-
492 s.reserve(128);-
493 switch (type) {-
494 case SelectStatement:
executed 293 times by 3 tests: case SelectStatement:
Executed by:
  • tst_QItemModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
293
495 for (i = 0; i < rec.count(); ++i) {
i < rec.count()Description
TRUEevaluated 721 times by 3 tests
Evaluated by:
  • tst_QItemModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
FALSEevaluated 293 times by 3 tests
Evaluated by:
  • tst_QItemModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
293-721
496 if (rec.isGenerated(i))
rec.isGenerated(i)Description
TRUEevaluated 721 times by 3 tests
Evaluated by:
  • tst_QItemModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
FALSEnever evaluated
0-721
497 s.append(prepareIdentifier(rec.fieldName(i), QSqlDriver::FieldName, this)).append(QLatin1String(", "));
executed 721 times by 3 tests: s.append(prepareIdentifier(rec.fieldName(i), QSqlDriver::FieldName, this)).append(QLatin1String(", "));
Executed by:
  • tst_QItemModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
721
498 }
executed 721 times by 3 tests: end of block
Executed by:
  • tst_QItemModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
721
499 if (s.isEmpty())
s.isEmpty()Description
TRUEnever evaluated
FALSEevaluated 293 times by 3 tests
Evaluated by:
  • tst_QItemModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
0-293
500 return s;
never executed: return s;
0
501 s.chop(2);-
502 s.prepend(QLatin1String("SELECT ")).append(QLatin1String(" FROM ")).append(tableName);-
503 break;
executed 293 times by 3 tests: break;
Executed by:
  • tst_QItemModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
293
504 case WhereStatement:
executed 135 times by 3 tests: case WhereStatement:
Executed by:
  • tst_QSqlDatabase
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
135
505 {-
506 const QString tableNamePrefix = tableName.isEmpty()
tableName.isEmpty()Description
TRUEnever evaluated
FALSEevaluated 135 times by 3 tests
Evaluated by:
  • tst_QSqlDatabase
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
0-135
507 ? QString()-
508 : prepareIdentifier(tableName, QSqlDriver::TableName, this) + QLatin1Char('.');-
509 for (int i = 0; i < rec.count(); ++i) {
i < rec.count()Description
TRUEevaluated 286 times by 3 tests
Evaluated by:
  • tst_QSqlDatabase
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
FALSEevaluated 135 times by 3 tests
Evaluated by:
  • tst_QSqlDatabase
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
135-286
510 if (!rec.isGenerated(i))
!rec.isGenerated(i)Description
TRUEnever evaluated
FALSEevaluated 286 times by 3 tests
Evaluated by:
  • tst_QSqlDatabase
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
0-286
511 continue;
never executed: continue;
0
512 s.append(s.isEmpty() ? QLatin1String("WHERE ") : QLatin1String(" AND "));-
513 s.append(tableNamePrefix);-
514 s.append(prepareIdentifier(rec.fieldName(i), QSqlDriver::FieldName, this));-
515 if (rec.isNull(i))
rec.isNull(i)Description
TRUEevaluated 17 times by 2 tests
Evaluated by:
  • tst_QSqlDatabase
  • tst_QSqlTableModel
FALSEevaluated 269 times by 3 tests
Evaluated by:
  • tst_QSqlDatabase
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
17-269
516 s.append(QLatin1String(" IS NULL"));
executed 17 times by 2 tests: s.append(QLatin1String(" IS NULL"));
Executed by:
  • tst_QSqlDatabase
  • tst_QSqlTableModel
17
517 else if (preparedStatement)
preparedStatementDescription
TRUEevaluated 152 times by 3 tests
Evaluated by:
  • tst_QSqlDatabase
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
FALSEevaluated 117 times by 3 tests
Evaluated by:
  • tst_QSqlDatabase
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
117-152
518 s.append(QLatin1String(" = ?"));
executed 152 times by 3 tests: s.append(QLatin1String(" = ?"));
Executed by:
  • tst_QSqlDatabase
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
152
519 else-
520 s.append(QLatin1String(" = ")).append(formatValue(rec.field(i)));
executed 117 times by 3 tests: s.append(QLatin1String(" = ")).append(formatValue(rec.field(i)));
Executed by:
  • tst_QSqlDatabase
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
117
521 }-
522 break;
executed 135 times by 3 tests: break;
Executed by:
  • tst_QSqlDatabase
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
135
523 }-
524 case UpdateStatement:
executed 49 times by 2 tests: case UpdateStatement:
Executed by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
49
525 s.append(QLatin1String("UPDATE ")).append(tableName).append(-
526 QLatin1String(" SET "));-
527 for (i = 0; i < rec.count(); ++i) {
i < rec.count()Description
TRUEevaluated 153 times by 2 tests
Evaluated by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
FALSEevaluated 49 times by 2 tests
Evaluated by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
49-153
528 if (!rec.isGenerated(i))
!rec.isGenerated(i)Description
TRUEevaluated 89 times by 2 tests
Evaluated by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
FALSEevaluated 64 times by 2 tests
Evaluated by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
64-89
529 continue;
executed 89 times by 2 tests: continue;
Executed by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
89
530 s.append(prepareIdentifier(rec.fieldName(i), QSqlDriver::FieldName, this)).append(QLatin1Char('='));-
531 if (preparedStatement)
preparedStatementDescription
TRUEevaluated 64 times by 2 tests
Evaluated by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
FALSEnever evaluated
0-64
532 s.append(QLatin1Char('?'));
executed 64 times by 2 tests: s.append(QLatin1Char('?'));
Executed by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
64
533 else-
534 s.append(formatValue(rec.field(i)));
never executed: s.append(formatValue(rec.field(i)));
0
535 s.append(QLatin1String(", "));-
536 }
executed 64 times by 2 tests: end of block
Executed by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
64
537 if (s.endsWith(QLatin1String(", ")))
s.endsWith(QLa...1String(", "))Description
TRUEevaluated 49 times by 2 tests
Evaluated by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
FALSEnever evaluated
0-49
538 s.chop(2);
executed 49 times by 2 tests: s.chop(2);
Executed by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
49
539 else-
540 s.clear();
never executed: s.clear();
0
541 break;
executed 49 times by 2 tests: break;
Executed by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
49
542 case DeleteStatement:
executed 22 times by 1 test: case DeleteStatement:
Executed by:
  • tst_QSqlTableModel
22
543 s.append(QLatin1String("DELETE FROM ")).append(tableName);-
544 break;
executed 22 times by 1 test: break;
Executed by:
  • tst_QSqlTableModel
22
545 case InsertStatement: {
executed 53 times by 2 tests: case InsertStatement:
Executed by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
53
546 s.append(QLatin1String("INSERT INTO ")).append(tableName).append(QLatin1String(" ("));-
547 QString vals;-
548 for (i = 0; i < rec.count(); ++i) {
i < rec.count()Description
TRUEevaluated 145 times by 2 tests
Evaluated by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
FALSEevaluated 53 times by 2 tests
Evaluated by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
53-145
549 if (!rec.isGenerated(i))
!rec.isGenerated(i)Description
TRUEevaluated 17 times by 1 test
Evaluated by:
  • tst_QSqlTableModel
FALSEevaluated 128 times by 2 tests
Evaluated by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
17-128
550 continue;
executed 17 times by 1 test: continue;
Executed by:
  • tst_QSqlTableModel
17
551 s.append(prepareIdentifier(rec.fieldName(i), QSqlDriver::FieldName, this)).append(QLatin1String(", "));-
552 if (preparedStatement)
preparedStatementDescription
TRUEevaluated 128 times by 2 tests
Evaluated by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
FALSEnever evaluated
0-128
553 vals.append(QLatin1Char('?'));
executed 128 times by 2 tests: vals.append(QLatin1Char('?'));
Executed by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
128
554 else-
555 vals.append(formatValue(rec.field(i)));
never executed: vals.append(formatValue(rec.field(i)));
0
556 vals.append(QLatin1String(", "));-
557 }
executed 128 times by 2 tests: end of block
Executed by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
128
558 if (vals.isEmpty()) {
vals.isEmpty()Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • tst_QSqlTableModel
FALSEevaluated 52 times by 2 tests
Evaluated by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
1-52
559 s.clear();-
560 } else {
executed 1 time by 1 test: end of block
Executed by:
  • tst_QSqlTableModel
1
561 vals.chop(2); // remove trailing comma-
562 s[s.length() - 2] = QLatin1Char(')');-
563 s.append(QLatin1String("VALUES (")).append(vals).append(QLatin1Char(')'));-
564 }
executed 52 times by 2 tests: end of block
Executed by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
52
565 break; }
executed 53 times by 2 tests: break;
Executed by:
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
53
566 }-
567 return s;
executed 552 times by 4 tests: return s;
Executed by:
  • tst_QItemModel
  • tst_QSqlDatabase
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
552
568}-
569-
570/*!-
571 Returns a string representation of the \a field value for the-
572 database. This is used, for example, when constructing INSERT and-
573 UPDATE statements.-
574-
575 The default implementation returns the value formatted as a string-
576 according to the following rules:-
577-
578 \list-
579-
580 \li If \a field is character data, the value is returned enclosed-
581 in single quotation marks, which is appropriate for many SQL-
582 databases. Any embedded single-quote characters are escaped-
583 (replaced with two single-quote characters). If \a trimStrings is-
584 true (the default is false), all trailing whitespace is trimmed-
585 from the field.-
586-
587 \li If \a field is date/time data, the value is formatted in ISO-
588 format and enclosed in single quotation marks. If the date/time-
589 data is invalid, "NULL" is returned.-
590-
591 \li If \a field is \l{QByteArray}{bytearray} data, and the-
592 driver can edit binary fields, the value is formatted as a-
593 hexadecimal string.-
594-
595 \li For any other field type, toString() is called on its value-
596 and the result of this is returned.-
597-
598 \endlist-
599-
600 \sa QVariant::toString()-
601-
602*/-
603QString QSqlDriver::formatValue(const QSqlField &field, bool trimStrings) const-
604{-
605 const QLatin1String nullTxt("NULL");-
606-
607 QString r;-
608 if (field.isNull())
field.isNull()Description
TRUEnever evaluated
FALSEevaluated 126 times by 4 tests
Evaluated by:
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
0-126
609 r = nullTxt;
never executed: r = nullTxt;
0
610 else {-
611 switch (field.type()) {-
612 case QVariant::Int:
executed 82 times by 4 tests: case QVariant::Int:
Executed by:
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
82
613 case QVariant::UInt:
never executed: case QVariant::UInt:
0
614 if (field.value().type() == QVariant::Bool)
field.value()....QVariant::BoolDescription
TRUEnever evaluated
FALSEevaluated 82 times by 4 tests
Evaluated by:
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
0-82
615 r = field.value().toBool() ? QLatin1String("1") : QLatin1String("0");
never executed: r = field.value().toBool() ? QLatin1String("1") : QLatin1String("0");
field.value().toBool()Description
TRUEnever evaluated
FALSEnever evaluated
0
616 else-
617 r = field.value().toString();
executed 82 times by 4 tests: r = field.value().toString();
Executed by:
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
82
618 break;
executed 82 times by 4 tests: break;
Executed by:
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
82
619#ifndef QT_NO_DATESTRING-
620 case QVariant::Date:
never executed: case QVariant::Date:
0
621 if (field.value().toDate().isValid())
field.value()....te().isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
622 r = QLatin1Char('\'') + field.value().toDate().toString(Qt::ISODate)
never executed: r = QLatin1Char('\'') + field.value().toDate().toString(Qt::ISODate) + QLatin1Char('\'');
0
623 + QLatin1Char('\'');
never executed: r = QLatin1Char('\'') + field.value().toDate().toString(Qt::ISODate) + QLatin1Char('\'');
0
624 else-
625 r = nullTxt;
never executed: r = nullTxt;
0
626 break;
never executed: break;
0
627 case QVariant::Time:
never executed: case QVariant::Time:
0
628 if (field.value().toTime().isValid())
field.value()....me().isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
629 r = QLatin1Char('\'') + field.value().toTime().toString(Qt::ISODate)
never executed: r = QLatin1Char('\'') + field.value().toTime().toString(Qt::ISODate) + QLatin1Char('\'');
0
630 + QLatin1Char('\'');
never executed: r = QLatin1Char('\'') + field.value().toTime().toString(Qt::ISODate) + QLatin1Char('\'');
0
631 else-
632 r = nullTxt;
never executed: r = nullTxt;
0
633 break;
never executed: break;
0
634 case QVariant::DateTime:
never executed: case QVariant::DateTime:
0
635 if (field.value().toDateTime().isValid())
field.value()....me().isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
636 r = QLatin1Char('\'') +
never executed: r = QLatin1Char('\'') + field.value().toDateTime().toString(Qt::ISODate) + QLatin1Char('\'');
0
637 field.value().toDateTime().toString(Qt::ISODate) + QLatin1Char('\'');
never executed: r = QLatin1Char('\'') + field.value().toDateTime().toString(Qt::ISODate) + QLatin1Char('\'');
0
638 else-
639 r = nullTxt;
never executed: r = nullTxt;
0
640 break;
never executed: break;
0
641#endif-
642 case QVariant::String:
executed 43 times by 3 tests: case QVariant::String:
Executed by:
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlTableModel
43
643 case QVariant::Char:
never executed: case QVariant::Char:
0
644 {-
645 QString result = field.value().toString();-
646 if (trimStrings) {
trimStringsDescription
TRUEevaluated 6 times by 1 test
Evaluated by:
  • tst_QSqlDatabase
FALSEevaluated 37 times by 3 tests
Evaluated by:
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlTableModel
6-37
647 int end = result.length();-
648 while (end && result.at(end-1).isSpace()) /* skip white space from end */
endDescription
TRUEevaluated 13 times by 1 test
Evaluated by:
  • tst_QSqlDatabase
FALSEevaluated 2 times by 1 test
Evaluated by:
  • tst_QSqlDatabase
result.at(end-1).isSpace()Description
TRUEevaluated 9 times by 1 test
Evaluated by:
  • tst_QSqlDatabase
FALSEevaluated 4 times by 1 test
Evaluated by:
  • tst_QSqlDatabase
2-13
649 end--;
executed 9 times by 1 test: end--;
Executed by:
  • tst_QSqlDatabase
9
650 result.truncate(end);-
651 }
executed 6 times by 1 test: end of block
Executed by:
  • tst_QSqlDatabase
6
652 /* escape the "'" character */-
653 result.replace(QLatin1Char('\''), QLatin1String("''"));-
654 r = QLatin1Char('\'') + result + QLatin1Char('\'');-
655 break;
executed 43 times by 3 tests: break;
Executed by:
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlTableModel
43
656 }-
657 case QVariant::Bool:
never executed: case QVariant::Bool:
0
658 r = QString::number(field.value().toBool());-
659 break;
never executed: break;
0
660 case QVariant::ByteArray : {
never executed: case QVariant::ByteArray :
0
661 if (hasFeature(BLOB)) {
hasFeature(BLOB)Description
TRUEnever evaluated
FALSEnever evaluated
0
662 QByteArray ba = field.value().toByteArray();-
663 QString res;-
664 static const char hexchars[] = "0123456789abcdef";-
665 for (int i = 0; i < ba.size(); ++i) {
i < ba.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
666 uchar s = (uchar) ba[i];-
667 res += QLatin1Char(hexchars[s >> 4]);-
668 res += QLatin1Char(hexchars[s & 0x0f]);-
669 }
never executed: end of block
0
670 r = QLatin1Char('\'') + res + QLatin1Char('\'');-
671 break;
never executed: break;
0
672 }-
673 }-
674 // fall through-
675 default:
code before this statement never executed: default:
executed 1 time by 1 test: default:
Executed by:
  • tst_QSqlDriver
0-1
676 r = field.value().toString();-
677 break;
executed 1 time by 1 test: break;
Executed by:
  • tst_QSqlDriver
1
678 }-
679 }-
680 return r;
executed 126 times by 4 tests: return r;
Executed by:
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
126
681}-
682-
683/*!-
684 Returns the low-level database handle wrapped in a QVariant or an-
685 invalid variant if there is no handle.-
686-
687 \warning Use this with uttermost care and only if you know what you're doing.-
688-
689 \warning The handle returned here can become a stale pointer if the connection-
690 is modified (for example, if you close the connection).-
691-
692 \warning The handle can be NULL if the connection is not open yet.-
693-
694 The handle returned here is database-dependent, you should query the type-
695 name of the variant before accessing it.-
696-
697 This example retrieves the handle for a connection to sqlite:-
698-
699 \snippet code/src_sql_kernel_qsqldriver.cpp 0-
700-
701 This snippet returns the handle for PostgreSQL or MySQL:-
702-
703 \snippet code/src_sql_kernel_qsqldriver.cpp 1-
704-
705 \sa QSqlResult::handle()-
706*/-
707QVariant QSqlDriver::handle() const-
708{-
709 return QVariant();
never executed: return QVariant();
0
710}-
711-
712/*!-
713 This function is called to subscribe to event notifications from the database.-
714 \a name identifies the event notification.-
715-
716 If successful, return true, otherwise return false.-
717-
718 The database must be open when this function is called. When the database is closed-
719 by calling close() all subscribed event notifications are automatically unsubscribed.-
720 Note that calling open() on an already open database may implicitly cause close() to-
721 be called, which will cause the driver to unsubscribe from all event notifications.-
722-
723 When an event notification identified by \a name is posted by the database the-
724 notification() signal is emitted.-
725-
726 Reimplement this function if you want to provide event notification support in your-
727 own QSqlDriver subclass,-
728-
729 \since 4.4-
730 \sa unsubscribeFromNotification(), subscribedToNotifications(), QSqlDriver::hasFeature()-
731*/-
732bool QSqlDriver::subscribeToNotification(const QString &name)-
733{-
734 Q_UNUSED(name);-
735 return false;
never executed: return false;
0
736}-
737-
738/*!-
739 This function is called to unsubscribe from event notifications from the database.-
740 \a name identifies the event notification.-
741-
742 If successful, return true, otherwise return false.-
743-
744 The database must be open when this function is called. All subscribed event-
745 notifications are automatically unsubscribed from when the close() function is called.-
746-
747 After calling \e this function the notification() signal will no longer be emitted-
748 when an event notification identified by \a name is posted by the database.-
749-
750 Reimplement this function if you want to provide event notification support in your-
751 own QSqlDriver subclass,-
752-
753 \since 4.4-
754 \sa subscribeToNotification(), subscribedToNotifications()-
755*/-
756bool QSqlDriver::unsubscribeFromNotification(const QString &name)-
757{-
758 Q_UNUSED(name);-
759 return false;
never executed: return false;
0
760}-
761-
762/*!-
763 Returns a list of the names of the event notifications that are currently subscribed to.-
764-
765 Reimplement this function if you want to provide event notification support in your-
766 own QSqlDriver subclass,-
767-
768 \since 4.4-
769 \sa subscribeToNotification(), unsubscribeFromNotification()-
770*/-
771QStringList QSqlDriver::subscribedToNotifications() const-
772{-
773 return QStringList();
never executed: return QStringList();
0
774}-
775-
776/*!-
777 \since 4.6-
778-
779 Sets the default numerical precision policy used by queries created-
780 by this driver to \a precisionPolicy.-
781-
782 Note: Setting the default precision policy to \a precisionPolicy-
783 doesn't affect any currently active queries.-
784-
785 \sa QSql::NumericalPrecisionPolicy, numericalPrecisionPolicy(),-
786 QSqlQuery::setNumericalPrecisionPolicy(), QSqlQuery::numericalPrecisionPolicy()-
787*/-
788void QSqlDriver::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy precisionPolicy)-
789{-
790 Q_D(QSqlDriver);-
791 d->precisionPolicy = precisionPolicy;-
792}
executed 2 times by 1 test: end of block
Executed by:
  • tst_QSqlDatabase
2
793-
794/*!-
795 \since 4.6-
796-
797 Returns the current default precision policy for the database connection.-
798-
799 \sa QSql::NumericalPrecisionPolicy, setNumericalPrecisionPolicy(),-
800 QSqlQuery::numericalPrecisionPolicy(), QSqlQuery::setNumericalPrecisionPolicy()-
801*/-
802QSql::NumericalPrecisionPolicy QSqlDriver::numericalPrecisionPolicy() const-
803{-
804 Q_D(const QSqlDriver);-
805 return d->precisionPolicy;
executed 2194 times by 10 tests: return d->precisionPolicy;
Executed by:
  • tst_QItemModel
  • tst_QSql
  • tst_QSqlDatabase
  • tst_QSqlDriver
  • tst_QSqlQuery
  • tst_QSqlQueryModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
  • tst_QSqlThread
  • tst_qsqlresult - unknown status
2194
806}-
807-
808/*!-
809 \since 5.4-
810-
811 Returns the current DBMS type for the database connection.-
812*/-
813QSqlDriver::DbmsType QSqlDriver::dbmsType() const-
814{-
815 Q_D(const QSqlDriver);-
816 return d->dbmsType;
executed 270 times by 8 tests: return d->dbmsType;
Executed by:
  • tst_QItemModel
  • tst_QSqlDatabase
  • tst_QSqlQuery
  • tst_QSqlQueryModel
  • tst_QSqlRelationalTableModel
  • tst_QSqlTableModel
  • tst_QSqlThread
  • tst_qsqlresult - unknown status
270
817}-
818-
819/*!-
820 \since 5.0-
821 \internal-
822-
823 Tries to cancel the running query, if the underlying driver has the-
824 capability to cancel queries. Returns \c true on success, otherwise false.-
825-
826 This function can be called from a different thread.-
827-
828 If you use this function as a slot, you need to use a Qt::DirectConnection-
829 from a different thread.-
830-
831 Reimplement this function to support canceling running queries in-
832 your own QSqlDriver subclass. It must be implemented in a thread-safe-
833 manner.-
834-
835 \sa QSqlDriver::hasFeature()-
836*/-
837bool QSqlDriver::cancelQuery()-
838{-
839 return false;
never executed: return false;
0
840}-
841-
842QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9