Akonadi

qsql_sqlite.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: Nokia Corporation ([email protected])
5 **
6 ** This file is part of the QtSql module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial Usage
10 ** Licensees holding valid Qt Commercial licenses may use this file in
11 ** accordance with the Qt Commercial License Agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Nokia.
14 **
15 ** GNU Lesser General Public License Usage
16 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** General Public License version 2.1 as published by the Free Software
18 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** packaging of this file. Please review the following information to
20 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** will be met: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 **
23 ** In addition, as a special exception, Nokia gives you certain additional
24 ** rights. These rights are described in the Nokia Qt LGPL Exception
25 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
26 **
27 ** GNU General Public License Usage
28 ** Alternatively, this file may be used under the terms of the GNU
29 ** General Public License version 3.0 as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL included in the
31 ** packaging of this file. Please review the following information to
32 ** ensure the GNU General Public License version 3.0 requirements will be
33 ** met: http://www.gnu.org/copyleft/gpl.html.
34 **
35 ** If you have questions regarding the use of this file, please contact
36 ** Nokia at [email protected]
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #include "qsql_sqlite.h"
42 
43 #include <QCoreApplication>
44 #include <QDateTime>
45 #include <QVariant>
46 #include <QSqlError>
47 #include <QSqlField>
48 #include <QSqlIndex>
49 #include <QSqlQuery>
50 #include <QStringList>
51 #include <QVector>
52 
53 #include <QtSql/private/qsqldriver_p.h>
54 #include <QtSql/private/qsqlcachedresult_p.h>
55 
56 #if defined Q_OS_WIN
57 # include <qt_windows.h>
58 #else
59 # include <unistd.h>
60 #endif
61 
62 #include <sqlite3.h>
63 
64 #include <QThread>
65 #include "sqlite_blocking.h"
66 
67 Q_DECLARE_OPAQUE_POINTER(sqlite3 *)
68 Q_DECLARE_OPAQUE_POINTER(sqlite3_stmt *)
69 
70 Q_DECLARE_METATYPE(sqlite3 *)
71 Q_DECLARE_METATYPE(sqlite3_stmt *)
72 
73 QT_BEGIN_NAMESPACE
74 
75 static QString _q_escapeIdentifier(const QString &identifier)
76 {
77  QString res = identifier;
78  if (!identifier.isEmpty() && identifier.at(0) != QString(QLatin1Char('"')) && identifier.right(1) != QString(QLatin1Char('"'))) {
79  res.replace(QLatin1Char('"'), QStringLiteral("\"\""));
80  res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
81  res.replace(QLatin1Char('.'), QStringLiteral("\".\""));
82  }
83  return res;
84 }
85 
86 static QVariant::Type qGetColumnType(const QString &tpName)
87 {
88  const QString typeName = tpName.toLower();
89 
90  if (typeName == QLatin1String("integer")
91  || typeName == QLatin1String("int")) {
92  return QVariant::Int;
93  }
94  if (typeName == QLatin1String("double")
95  || typeName == QLatin1String("float")
96  || typeName == QLatin1String("real")
97  || typeName.startsWith(QLatin1String("numeric"))) {
98  return QVariant::Double;
99  }
100  if (typeName == QLatin1String("blob")) {
101  return QVariant::ByteArray;
102  }
103  if (typeName == QLatin1String("boolean")
104  || typeName == QLatin1String("bool")) {
105  return QVariant::Bool;
106  }
107  return QVariant::String;
108 }
109 
110 static QSqlError qMakeError(sqlite3 *access, const QString &descr, QSqlError::ErrorType type,
111  int errorCode = -1)
112 {
113  return QSqlError(descr,
114  QString(reinterpret_cast<const QChar *>(sqlite3_errmsg16(access))),
115  type, QString::number(errorCode));
116 }
117 
118 class QSQLiteResultPrivate;
119 
120 class QSQLiteResult : public QSqlCachedResult
121 {
122  friend class QSQLiteDriver;
123  friend class QSQLiteResultPrivate;
124 public:
125  explicit QSQLiteResult(const QSQLiteDriver *db);
126  ~QSQLiteResult();
127  QVariant handle() const override;
128 
129 protected:
130  bool gotoNext(QSqlCachedResult::ValueCache &row, int idx) override;
131  bool reset(const QString &query) override;
132  bool prepare(const QString &query) override;
133  bool exec() override;
134  int size() override;
135  int numRowsAffected() override;
136  QVariant lastInsertId() const override;
137  QSqlRecord record() const override;
138  void detachFromResultSet() override;
139  void virtual_hook(int id, void *data) override;
140 
141 private:
142  Q_DECLARE_PRIVATE(QSQLiteResult)
143 };
144 
145 class QSQLiteDriverPrivate : public QSqlDriverPrivate
146 {
147 public:
148  inline QSQLiteDriverPrivate() : access(nullptr)
149  {
150  dbmsType = QSqlDriver::SQLite;
151  }
152  sqlite3 *access;
153  QList<QSQLiteResult *> results;
154 };
155 
156 class QSQLiteResultPrivate : public QSqlCachedResultPrivate
157 {
158 public:
159  QSQLiteResultPrivate(QSQLiteResult *res, const QSQLiteDriver *drv);
160 
161  void cleanup();
162  bool fetchNext(QSqlCachedResult::ValueCache &values, int idx, bool initialFetch);
163  // initializes the recordInfo and the cache
164  void initColumns(bool emptyResultset);
165  void finalize();
166 
167  sqlite3 *access;
168 
169  sqlite3_stmt *stmt;
170 
171  bool skippedStatus; // the status of the fetchNext() that's skipped
172  bool skipRow; // skip the next fetchNext()?
173  QSqlRecord rInf;
174  QVector<QVariant> firstRow;
175 
176  Q_DECLARE_PUBLIC(QSQLiteResult)
177 };
178 
179 QSQLiteResultPrivate::QSQLiteResultPrivate(QSQLiteResult *res, const QSQLiteDriver *drv)
180  : QSqlCachedResultPrivate(res, drv)
181  , access(nullptr)
182  , stmt(nullptr)
183  , skippedStatus(false)
184  , skipRow(false)
185 {
186 }
187 
188 void QSQLiteResultPrivate::cleanup()
189 {
190  Q_Q(QSQLiteResult);
191  finalize();
192  rInf.clear();
193  skippedStatus = false;
194  skipRow = false;
195  q->setAt(QSql::BeforeFirstRow);
196  q->setActive(false);
197  q->cleanup();
198 }
199 
200 void QSQLiteResultPrivate::finalize()
201 {
202  if (!stmt) {
203  return;
204  }
205 
206  sqlite3_finalize(stmt);
207  stmt = nullptr;
208 }
209 
210 void QSQLiteResultPrivate::initColumns(bool emptyResultset)
211 {
212  Q_Q(QSQLiteResult);
213  int nCols = sqlite3_column_count(stmt);
214  if (nCols <= 0) {
215  return;
216  }
217 
218  q->init(nCols);
219 
220  for (int i = 0; i < nCols; ++i) {
221  QString colName = QString::fromUtf16(
222  static_cast<const ushort *>(sqlite3_column_name16(stmt, i))
223  ).remove(QLatin1Char('"'));
224 
225  // must use typeName for resolving the type to match QSqliteDriver::record
226  QString typeName = QString::fromUtf16(
227  static_cast<const ushort *>(sqlite3_column_decltype16(stmt, i)));
228 
229  // sqlite3_column_type is documented to have undefined behavior if the result set is empty
230  int stp = emptyResultset ? -1 : sqlite3_column_type(stmt, i);
231 
232  QVariant::Type fieldType;
233 
234  if (typeName.isEmpty()) {
235  fieldType = qGetColumnType(typeName);
236  } else {
237  // Get the proper type for the field based on stp value
238  switch (stp) {
239  case SQLITE_INTEGER:
240  fieldType = QVariant::Int;
241  break;
242  case SQLITE_FLOAT:
243  fieldType = QVariant::Double;
244  break;
245  case SQLITE_BLOB:
246  fieldType = QVariant::ByteArray;
247  break;
248  case SQLITE_TEXT:
249  fieldType = QVariant::String;
250  break;
251  case SQLITE_NULL:
252  default:
253  fieldType = QVariant::Invalid;
254  break;
255  }
256  }
257 
258  QSqlField fld(colName, fieldType);
259  fld.setSqlType(stp);
260  rInf.append(fld);
261  }
262 }
263 
264 bool QSQLiteResultPrivate::fetchNext(QSqlCachedResult::ValueCache &values, int idx, bool initialFetch)
265 {
266  Q_Q(QSQLiteResult);
267 
268  int res;
269  int i;
270 
271  if (skipRow) {
272  // already fetched
273  Q_ASSERT(!initialFetch);
274  skipRow = false;
275  for (int i = 0; i < firstRow.count(); i++) {
276  values[i] = firstRow[i];
277  }
278  return skippedStatus;
279  }
280  skipRow = initialFetch;
281 
282  if (initialFetch) {
283  firstRow.clear();
284  firstRow.resize(sqlite3_column_count(stmt));
285  }
286 
287  if (!stmt) {
288  q->setLastError(QSqlError(QCoreApplication::translate("QSQLiteResult", "Unable to fetch row"),
289  QCoreApplication::translate("QSQLiteResult", "No query"), QSqlError::ConnectionError));
290  q->setAt(QSql::AfterLastRow);
291  return false;
292  }
293  res = sqlite3_blocking_step(stmt);
294 
295  switch (res) {
296  case SQLITE_ROW:
297  // check to see if should fill out columns
298  if (rInf.isEmpty())
299  // must be first call.
300  {
301  initColumns(false);
302  }
303  if (idx < 0 && !initialFetch) {
304  return true;
305  }
306  for (i = 0; i < rInf.count(); ++i) {
307  switch (sqlite3_column_type(stmt, i)) {
308  case SQLITE_BLOB:
309  values[i + idx] = QByteArray(static_cast<const char *>(
310  sqlite3_column_blob(stmt, i)),
311  sqlite3_column_bytes(stmt, i));
312  break;
313  case SQLITE_INTEGER:
314  values[i + idx] = sqlite3_column_int64(stmt, i);
315  break;
316  case SQLITE_FLOAT:
317  switch (q->numericalPrecisionPolicy()) {
318  case QSql::LowPrecisionInt32:
319  values[i + idx] = sqlite3_column_int(stmt, i);
320  break;
321  case QSql::LowPrecisionInt64:
322  values[i + idx] = sqlite3_column_int64(stmt, i);
323  break;
324  case QSql::LowPrecisionDouble:
325  case QSql::HighPrecision:
326  default:
327  values[i + idx] = sqlite3_column_double(stmt, i);
328  break;
329  };
330  break;
331  case SQLITE_NULL:
332  values[i + idx] = QVariant(QVariant::String);
333  break;
334  default:
335  values[i + idx] = QString(reinterpret_cast<const QChar *>(
336  sqlite3_column_text16(stmt, i)),
337  sqlite3_column_bytes16(stmt, i) / sizeof(QChar));
338  break;
339  }
340  }
341  return true;
342  case SQLITE_DONE:
343  if (rInf.isEmpty())
344  // must be first call.
345  {
346  initColumns(true);
347  }
348  q->setAt(QSql::AfterLastRow);
349  sqlite3_reset(stmt);
350  return false;
351  case SQLITE_CONSTRAINT:
352  case SQLITE_ERROR:
353  // SQLITE_ERROR is a generic error code and we must call sqlite3_reset()
354  // to get the specific error message.
355  res = sqlite3_reset(stmt);
356  q->setLastError(qMakeError(access, QCoreApplication::translate("QSQLiteResult",
357  "Unable to fetch row"), QSqlError::ConnectionError, res));
358  q->setAt(QSql::AfterLastRow);
359  return false;
360  case SQLITE_MISUSE:
361  case SQLITE_BUSY:
362  default:
363  // something wrong, don't get col info, but still return false
364  q->setLastError(qMakeError(access, QCoreApplication::translate("QSQLiteResult",
365  "Unable to fetch row"), QSqlError::ConnectionError, res));
366  sqlite3_reset(stmt);
367  q->setAt(QSql::AfterLastRow);
368  return false;
369  }
370  return false;
371 }
372 
373 QSQLiteResult::QSQLiteResult(const QSQLiteDriver *db)
374  : QSqlCachedResult(*new QSQLiteResultPrivate(this, db))
375 {
376  Q_D(QSQLiteResult);
377  d->access = db->d_func()->access;
378  const_cast<QSQLiteDriverPrivate *>(db->d_func())->results.append(this);
379 }
380 
381 QSQLiteResult::~QSQLiteResult()
382 {
383  Q_D(QSQLiteResult);
384  const QSqlDriver *sqlDriver = driver();
385  if (sqlDriver) {
386  const_cast<QSQLiteDriverPrivate *>(qobject_cast<const QSQLiteDriver *>(sqlDriver)->d_func())->results.removeOne(this);
387  }
388  d->cleanup();
389 }
390 
391 void QSQLiteResult::virtual_hook(int id, void *data)
392 {
393  QSqlCachedResult::virtual_hook(id, data);
394 }
395 
396 bool QSQLiteResult::reset(const QString &query)
397 {
398  if (!prepare(query)) {
399  return false;
400  }
401  return exec();
402 }
403 
404 bool QSQLiteResult::prepare(const QString &query)
405 {
406  Q_D(QSQLiteResult);
407 
408  if (!driver() || !driver()->isOpen() || driver()->isOpenError()) {
409  return false;
410  }
411 
412  d->cleanup();
413 
414  setSelect(false);
415 
416  const void *pzTail = nullptr;
417 
418 #if (SQLITE_VERSION_NUMBER >= 3003011)
419 // int res = sqlite3_prepare16_v2(d->access, query.constData(), (query.size() + 1) * sizeof(QChar),
420 // &d->stmt, 0);
421  int res = sqlite3_blocking_prepare16_v2(d->access, query.constData(), (query.size() + 1) * sizeof(QChar),
422  &d->stmt, &pzTail);
423 #else
424  int res = sqlite3_prepare16(d->access, query.constData(), (query.size() + 1) * sizeof(QChar),
425  &d->stmt, &pzTail);
426 #endif
427 
428  if (res != SQLITE_OK) {
429  setLastError(qMakeError(d->access, QCoreApplication::translate("QSQLiteResult",
430  "Unable to execute statement"), QSqlError::StatementError, res));
431  d->finalize();
432  return false;
433  } else if (pzTail && !QString(reinterpret_cast<const QChar *>(pzTail)).trimmed().isEmpty()) {
434  setLastError(qMakeError(d->access, QCoreApplication::translate("QSQLiteResult",
435  "Unable to execute multiple statements at a time"), QSqlError::StatementError, SQLITE_MISUSE));
436  d->finalize();
437  return false;
438  }
439  return true;
440 }
441 
442 bool QSQLiteResult::exec()
443 {
444  Q_D(QSQLiteResult);
445  const QVector<QVariant> values = boundValues();
446 
447  d->skippedStatus = false;
448  d->skipRow = false;
449  d->rInf.clear();
450  clearValues();
451  setLastError(QSqlError());
452 
453  int res = sqlite3_reset(d->stmt);
454  if (res != SQLITE_OK) {
455  setLastError(qMakeError(d->access, QCoreApplication::translate("QSQLiteResult",
456  "Unable to reset statement"), QSqlError::StatementError, res));
457  d->finalize();
458  return false;
459  }
460  int paramCount = sqlite3_bind_parameter_count(d->stmt);
461  if (paramCount == values.count()) {
462  for (int i = 0; i < paramCount; ++i) {
463  res = SQLITE_OK;
464  const QVariant value = values.at(i);
465 
466  if (value.isNull()) {
467  res = sqlite3_bind_null(d->stmt, i + 1);
468  } else {
469  switch (value.type()) {
470  case QVariant::ByteArray: {
471  const QByteArray *ba = static_cast<const QByteArray *>(value.constData());
472  res = sqlite3_bind_blob(d->stmt, i + 1, ba->constData(),
473  ba->size(), SQLITE_STATIC);
474  break;
475  }
476  case QVariant::Int:
477  case QVariant::Bool:
478  res = sqlite3_bind_int(d->stmt, i + 1, value.toInt());
479  break;
480  case QVariant::Double:
481  res = sqlite3_bind_double(d->stmt, i + 1, value.toDouble());
482  break;
483  case QVariant::UInt:
484  case QVariant::LongLong:
485  res = sqlite3_bind_int64(d->stmt, i + 1, value.toLongLong());
486  break;
487  case QVariant::DateTime: {
488  const QDateTime dateTime = value.toDateTime();
489  const QString str = dateTime.toString(QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz"));
490  res = sqlite3_bind_text16(d->stmt, i + 1, str.utf16(),
491  str.size() * sizeof(ushort), SQLITE_TRANSIENT);
492  break;
493  }
494  case QVariant::Time: {
495  const QTime time = value.toTime();
496  const QString str = time.toString(QStringLiteral("hh:mm:ss.zzz"));
497  res = sqlite3_bind_text16(d->stmt, i + 1, str.utf16(),
498  str.size() * sizeof(ushort), SQLITE_TRANSIENT);
499  break;
500  }
501  case QVariant::String: {
502  // lifetime of string == lifetime of its qvariant
503  const QString *str = static_cast<const QString *>(value.constData());
504  res = sqlite3_bind_text16(d->stmt, i + 1, str->utf16(),
505  (str->size()) * sizeof(QChar), SQLITE_STATIC);
506  break;
507  }
508  default: {
509  QString str = value.toString();
510  // SQLITE_TRANSIENT makes sure that sqlite buffers the data
511  res = sqlite3_bind_text16(d->stmt, i + 1, str.utf16(),
512  (str.size()) * sizeof(QChar), SQLITE_TRANSIENT);
513  break;
514  }
515  }
516  }
517  if (res != SQLITE_OK) {
518  setLastError(qMakeError(d->access, QCoreApplication::translate("QSQLiteResult",
519  "Unable to bind parameters"), QSqlError::StatementError, res));
520  d->finalize();
521  return false;
522  }
523  }
524  } else {
525  setLastError(QSqlError(QCoreApplication::translate("QSQLiteResult",
526  "Parameter count mismatch"), QString(), QSqlError::StatementError));
527  return false;
528  }
529  d->skippedStatus = d->fetchNext(d->firstRow, 0, true);
530  if (lastError().isValid()) {
531  setSelect(false);
532  setActive(false);
533  return false;
534  }
535  setSelect(!d->rInf.isEmpty());
536  setActive(true);
537  return true;
538 }
539 
540 bool QSQLiteResult::gotoNext(QSqlCachedResult::ValueCache &row, int idx)
541 {
542  return d_func()->fetchNext(row, idx, false);
543 }
544 
545 int QSQLiteResult::size()
546 {
547  return -1;
548 }
549 
550 int QSQLiteResult::numRowsAffected()
551 {
552  return sqlite3_changes(d_func()->access);
553 }
554 
555 QVariant QSQLiteResult::lastInsertId() const
556 {
557  if (isActive()) {
558  qint64 id = sqlite3_last_insert_rowid(d_func()->access);
559  if (id) {
560  return id;
561  }
562  }
563  return QVariant();
564 }
565 
566 QSqlRecord QSQLiteResult::record() const
567 {
568  if (!isActive() || !isSelect()) {
569  return QSqlRecord();
570  }
571  return d_func()->rInf;
572 }
573 
574 void QSQLiteResult::detachFromResultSet()
575 {
576  if (d_func()->stmt) {
577  sqlite3_reset(d_func()->stmt);
578  }
579 }
580 
581 QVariant QSQLiteResult::handle() const
582 {
583  return QVariant::fromValue(d_func()->stmt);
584 }
585 
587 
588 QSQLiteDriver::QSQLiteDriver(QObject *parent)
589  : QSqlDriver(*new QSQLiteDriverPrivate, parent)
590 {
591 }
592 
593 QSQLiteDriver::QSQLiteDriver(sqlite3 *connection, QObject *parent)
594  : QSqlDriver(*new QSQLiteDriverPrivate, parent)
595 {
596  Q_D(QSQLiteDriver);
597 
598  d->access = connection;
599  setOpen(true);
600  setOpenError(false);
601 }
602 
603 QSQLiteDriver::~QSQLiteDriver()
604 {
605 }
606 
607 bool QSQLiteDriver::hasFeature(DriverFeature f) const
608 {
609  switch (f) {
610  case BLOB:
611  case Transactions:
612  case Unicode:
613  case LastInsertId:
614  case PreparedQueries:
615  case PositionalPlaceholders:
616  case SimpleLocking:
617  case FinishQuery:
618  case LowPrecisionNumbers:
619  return true;
620  case QuerySize:
621  case NamedPlaceholders:
622  case BatchOperations:
623  case EventNotifications:
624  case MultipleResultSets:
625  case CancelQuery:
626  return false;
627  }
628  return false;
629 }
630 
631 /*
632  SQLite dbs have no user name, passwords, hosts or ports.
633  just file names.
634 */
635 bool QSQLiteDriver::open(const QString &db, const QString &, const QString &, const QString &, int, const QString &conOpts)
636 {
637  Q_D(QSQLiteDriver);
638 
639  if (isOpen()) {
640  close();
641  }
642 
643  int timeout = 5000;
644  bool sharedCache = false;
645  bool openReadOnlyOption = false;
646  bool openUriOption = false;
647 
648  const QStringList opts = QString(conOpts).remove(QLatin1Char(' ')).split(QLatin1Char(';'));
649  for (const QString &option : opts) {
650  if (option.startsWith(QLatin1String("QSQLITE_BUSY_TIMEOUT="))) {
651  bool ok;
652  const int nt = option.midRef(21).toInt(&ok);
653  if (ok) {
654  timeout = nt;
655  }
656  } else if (option == QLatin1String("QSQLITE_OPEN_READONLY")) {
657  openReadOnlyOption = true;
658  } else if (option == QLatin1String("QSQLITE_OPEN_URI")) {
659  openUriOption = true;
660  } else if (option == QLatin1String("QSQLITE_ENABLE_SHARED_CACHE")) {
661  sharedCache = true;
662  }
663  }
664 
665  int openMode = (openReadOnlyOption ? SQLITE_OPEN_READONLY : (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE));
666  if (openUriOption) {
667  openMode |= SQLITE_OPEN_URI;
668  }
669 
670  sqlite3_enable_shared_cache(sharedCache);
671 
672  if (sqlite3_open_v2(db.toUtf8().constData(), &d->access, openMode, nullptr) == SQLITE_OK) {
673  sqlite3_busy_timeout(d->access, timeout);
674  sqlite3_extended_result_codes(d->access, 1);
675  setOpen(true);
676  setOpenError(false);
677  return true;
678  } else {
679  if (d->access) {
680  sqlite3_close(d->access);
681  d->access = nullptr;
682  }
683 
684  setLastError(qMakeError(d->access, tr("Error opening database"),
685  QSqlError::ConnectionError));
686  setOpenError(true);
687  return false;
688  }
689 }
690 
691 void QSQLiteDriver::close()
692 {
693  Q_D(QSQLiteDriver);
694 
695  if (isOpen()) {
696  Q_FOREACH (QSQLiteResult *result, d->results) {
697  result->d_func()->finalize();
698  }
699 
700  if (sqlite3_close(d->access) != SQLITE_OK)
701  setLastError(qMakeError(d->access, tr("Error closing database"),
702  QSqlError::ConnectionError));
703  d->access = nullptr;
704  setOpen(false);
705  setOpenError(false);
706  }
707 }
708 
709 QSqlResult *QSQLiteDriver::createResult() const
710 {
711  return new QSQLiteResult(this);
712 }
713 
714 bool QSQLiteDriver::beginTransaction()
715 {
716  if (!isOpen() || isOpenError()) {
717  return false;
718  }
719 
720  QSqlQuery q(createResult());
721  if (!q.exec(QStringLiteral("BEGIN"))) {
722  setLastError(QSqlError(tr("Unable to begin transaction"),
723  q.lastError().databaseText(), QSqlError::TransactionError));
724  return false;
725  }
726 
727  return true;
728 }
729 
730 bool QSQLiteDriver::commitTransaction()
731 {
732  if (!isOpen() || isOpenError()) {
733  return false;
734  }
735 
736  QSqlQuery q(createResult());
737  if (!q.exec(QStringLiteral("COMMIT"))) {
738  setLastError(QSqlError(tr("Unable to commit transaction"),
739  q.lastError().databaseText(), QSqlError::TransactionError));
740  return false;
741  }
742 
743  return true;
744 }
745 
746 bool QSQLiteDriver::rollbackTransaction()
747 {
748  if (!isOpen() || isOpenError()) {
749  return false;
750  }
751 
752  QSqlQuery q(createResult());
753  if (!q.exec(QStringLiteral("ROLLBACK"))) {
754  setLastError(QSqlError(tr("Unable to rollback transaction"),
755  q.lastError().databaseText(), QSqlError::TransactionError));
756  return false;
757  }
758 
759  return true;
760 }
761 
762 QStringList QSQLiteDriver::tables(QSql::TableType type) const
763 {
764  QStringList res;
765  if (!isOpen()) {
766  return res;
767  }
768 
769  QSqlQuery q(createResult());
770  q.setForwardOnly(true);
771 
772  QString sql = QStringLiteral("SELECT name FROM sqlite_master WHERE %1 "
773  "UNION ALL SELECT name FROM sqlite_temp_master WHERE %1");
774  if ((type & QSql::Tables) && (type & QSql::Views)) {
775  sql = sql.arg(QStringLiteral("type='table' OR type='view'"));
776  } else if (type & QSql::Tables) {
777  sql = sql.arg(QStringLiteral("type='table'"));
778  } else if (type & QSql::Views) {
779  sql = sql.arg(QStringLiteral("type='view'"));
780  } else {
781  sql.clear();
782  }
783 
784  if (!sql.isEmpty() && q.exec(sql)) {
785  while (q.next()) {
786  res.append(q.value(0).toString());
787  }
788  }
789 
790  if (type & QSql::SystemTables) {
791  // there are no internal tables beside this one:
792  res.append(QStringLiteral("sqlite_master"));
793  }
794 
795  return res;
796 }
797 
798 static QSqlIndex qGetTableInfo(QSqlQuery &q, const QString &tableName, bool onlyPIndex = false)
799 {
800  QString schema;
801  QString table(tableName);
802  int indexOfSeparator = tableName.indexOf(QLatin1Char('.'));
803  if (indexOfSeparator > -1) {
804  schema = tableName.left(indexOfSeparator).append(QLatin1Char('.'));
805  table = tableName.mid(indexOfSeparator + 1);
806  }
807  q.exec(QStringLiteral("PRAGMA ") + schema + QStringLiteral("table_info (") + _q_escapeIdentifier(table) + QLatin1Char(')'));
808 
809  QSqlIndex ind;
810  while (q.next()) {
811  bool isPk = q.value(5).toInt();
812  if (onlyPIndex && !isPk) {
813  continue;
814  }
815  QString typeName = q.value(2).toString().toLower();
816  QSqlField fld(q.value(1).toString(), qGetColumnType(typeName));
817  if (isPk && (typeName == QLatin1String("integer")))
818  // INTEGER PRIMARY KEY fields are auto-generated in sqlite
819  // INT PRIMARY KEY is not the same as INTEGER PRIMARY KEY!
820  {
821  fld.setAutoValue(true);
822  }
823  fld.setRequired(q.value(3).toInt() != 0);
824  fld.setDefaultValue(q.value(4));
825  ind.append(fld);
826  }
827  return ind;
828 }
829 
830 QSqlIndex QSQLiteDriver::primaryIndex(const QString &tblname) const
831 {
832  if (!isOpen()) {
833  return QSqlIndex();
834  }
835 
836  QString table = tblname;
837  if (isIdentifierEscaped(table, QSqlDriver::TableName)) {
838  table = stripDelimiters(table, QSqlDriver::TableName);
839  }
840 
841  QSqlQuery q(createResult());
842  q.setForwardOnly(true);
843  return qGetTableInfo(q, table, true);
844 }
845 
846 QSqlRecord QSQLiteDriver::record(const QString &tbl) const
847 {
848  if (!isOpen()) {
849  return QSqlRecord();
850  }
851 
852  QString table = tbl;
853  if (isIdentifierEscaped(table, QSqlDriver::TableName)) {
854  table = stripDelimiters(table, QSqlDriver::TableName);
855  }
856 
857  QSqlQuery q(createResult());
858  q.setForwardOnly(true);
859  return qGetTableInfo(q, table);
860 }
861 
862 QVariant QSQLiteDriver::handle() const
863 {
864  Q_D(const QSQLiteDriver);
865  return QVariant::fromValue(d->access);
866 }
867 
868 QString QSQLiteDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const
869 {
870  Q_UNUSED(type);
871  return _q_escapeIdentifier(identifier);
872 }
873 
874 QT_END_NAMESPACE
qlonglong toLongLong(bool *ok) const const
QString toString(Qt::DateFormat format) const const
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
QString & append(QChar ch)
const QChar * constData() const const
QString toString(Qt::DateFormat format) const const
void setAutoValue(bool autoVal)
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
QDateTime toDateTime() const const
QString & prepend(QChar ch)
virtual QString escapeIdentifier(const QString &identifier, QSqlDriver::IdentifierType type) const const
bool exec(const QString &query)
QString translate(const char *context, const char *sourceText, const char *disambiguation, int n)
QTime toTime() const const
int size() const const
void append(const QSqlField &field)
QString & remove(int position, int n)
const QList< QKeySequence > & close()
QString tr(const char *sourceText, const char *disambiguation, int n)
void clear()
QString number(int n, int base)
void append(const T &value)
int toInt(bool *ok) const const
bool isNull() const const
QString fromUtf16(const ushort *unicode, int size)
QVariant value(int index) const const
bool isEmpty() const const
const char * constData() const const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
bool next()
void setForwardOnly(bool forward)
QString right(int n) const const
QString toLower() const const
QVariant fromValue(const T &value)
QString & replace(int position, int n, QChar after)
const T & at(int i) const const
const ushort * utf16() const const
QString mid(int position, int n) const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
int count(const T &value) const const
QString left(int n) const const
double toDouble(bool *ok) const const
KGuiItem reset()
QVariant::Type type() const const
int size() const const
T qobject_cast(QObject *object)
QObject * parent() const const
QString toString() const const
virtual bool hasFeature(QSqlDriver::DriverFeature feature) const const =0
QByteArray toUtf8() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Fri Jun 5 2020 23:08:55 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.