PageRenderTime 58ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/qt-everywhere-opensource-src-4.7.1/src/sql/models/qsqltablemodel.cpp

https://bitbucket.org/boroondas/3p-qt-open-83
C++ | 1340 lines | 776 code | 102 blank | 462 comment | 228 complexity | a02098c0c970cc1d4036db16c08c517f MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-3.0, BSD-3-Clause, GPL-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, GPL-3.0, CC-BY-SA-4.0, Apache-2.0
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
  4. ** All rights reserved.
  5. ** Contact: Nokia Corporation (qt-info@nokia.com)
  6. **
  7. ** This file is part of the QtSql module of the Qt Toolkit.
  8. **
  9. ** $QT_BEGIN_LICENSE:LGPL$
  10. ** Commercial Usage
  11. ** Licensees holding valid Qt Commercial licenses may use this file in
  12. ** accordance with the Qt Commercial License Agreement provided with the
  13. ** Software or, alternatively, in accordance with the terms contained in
  14. ** a written agreement between you and Nokia.
  15. **
  16. ** GNU Lesser General Public License Usage
  17. ** Alternatively, this file may be used under the terms of the GNU Lesser
  18. ** General Public License version 2.1 as published by the Free Software
  19. ** Foundation and appearing in the file LICENSE.LGPL included in the
  20. ** packaging of this file. Please review the following information to
  21. ** ensure the GNU Lesser General Public License version 2.1 requirements
  22. ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  23. **
  24. ** In addition, as a special exception, Nokia gives you certain additional
  25. ** rights. These rights are described in the Nokia Qt LGPL Exception
  26. ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  27. **
  28. ** GNU General Public License Usage
  29. ** Alternatively, this file may be used under the terms of the GNU
  30. ** General Public License version 3.0 as published by the Free Software
  31. ** Foundation and appearing in the file LICENSE.GPL included in the
  32. ** packaging of this file. Please review the following information to
  33. ** ensure the GNU General Public License version 3.0 requirements will be
  34. ** met: http://www.gnu.org/copyleft/gpl.html.
  35. **
  36. ** If you have questions regarding the use of this file, please contact
  37. ** Nokia at qt-info@nokia.com.
  38. ** $QT_END_LICENSE$
  39. **
  40. ****************************************************************************/
  41. #include "qsqltablemodel.h"
  42. #include "qsqldriver.h"
  43. #include "qsqlerror.h"
  44. #include "qsqlfield.h"
  45. #include "qsqlindex.h"
  46. #include "qsqlquery.h"
  47. #include "qsqlrecord.h"
  48. #include "qsqlresult.h"
  49. #include "qsqltablemodel_p.h"
  50. #include <qdebug.h>
  51. QT_BEGIN_NAMESPACE
  52. /*! \internal
  53. Populates our record with values.
  54. */
  55. QSqlRecord QSqlTableModelPrivate::record(const QVector<QVariant> &values) const
  56. {
  57. QSqlRecord r = rec;
  58. for (int i = 0; i < r.count() && i < values.count(); ++i)
  59. r.setValue(i, values.at(i));
  60. return r;
  61. }
  62. /*! \internal
  63. Set a record for OnFieldChange and OnRowChange.
  64. */
  65. bool QSqlTableModelPrivate::setRecord(int row, const QSqlRecord &record)
  66. {
  67. Q_Q(QSqlTableModel);
  68. bool isOk = true;
  69. QSqlTableModel::EditStrategy oldStrategy = strategy;
  70. // FieldChange strategy makes no sense when setting an entire row
  71. if (strategy == QSqlTableModel::OnFieldChange)
  72. strategy = QSqlTableModel::OnRowChange;
  73. for (int i = 0; i < record.count(); ++i) {
  74. int idx = nameToIndex(record.fieldName(i));
  75. if (idx == -1)
  76. continue;
  77. QModelIndex cIndex = q->createIndex(row, idx);
  78. QVariant value = record.value(i);
  79. QVariant oldValue = q->data(cIndex);
  80. if (oldValue.isNull() || oldValue != value)
  81. isOk &= q->setData(cIndex, value, Qt::EditRole);
  82. }
  83. if (isOk && oldStrategy == QSqlTableModel::OnFieldChange)
  84. q->submitAll();
  85. strategy = oldStrategy;
  86. return isOk;
  87. }
  88. int QSqlTableModelPrivate::nameToIndex(const QString &name) const
  89. {
  90. QString fieldname = name;
  91. if (db.driver()->isIdentifierEscaped(fieldname, QSqlDriver::FieldName))
  92. fieldname = db.driver()->stripDelimiters(fieldname, QSqlDriver::FieldName);
  93. return rec.indexOf(fieldname);
  94. }
  95. void QSqlTableModelPrivate::initRecordAndPrimaryIndex()
  96. {
  97. rec = db.record(tableName);
  98. primaryIndex = db.primaryIndex(tableName);
  99. }
  100. void QSqlTableModelPrivate::clear()
  101. {
  102. editIndex = -1;
  103. sortColumn = -1;
  104. sortOrder = Qt::AscendingOrder;
  105. tableName.clear();
  106. editQuery.clear();
  107. editBuffer.clear();
  108. cache.clear();
  109. primaryIndex.clear();
  110. rec.clear();
  111. filter.clear();
  112. }
  113. void QSqlTableModelPrivate::revertInsertedRow()
  114. {
  115. Q_Q(QSqlTableModel);
  116. if (insertIndex == -1)
  117. return;
  118. q->beginRemoveRows(QModelIndex(), insertIndex, insertIndex);
  119. insertIndex = -1;
  120. q->endRemoveRows();
  121. }
  122. void QSqlTableModelPrivate::clearEditBuffer()
  123. {
  124. editBuffer = rec;
  125. }
  126. void QSqlTableModelPrivate::clearCache()
  127. {
  128. cache.clear();
  129. }
  130. void QSqlTableModelPrivate::revertCachedRow(int row)
  131. {
  132. Q_Q(QSqlTableModel);
  133. ModifiedRow r = cache.value(row);
  134. switch (r.op) {
  135. case QSqlTableModelPrivate::None:
  136. Q_ASSERT_X(false, "QSqlTableModelPrivate::revertCachedRow()", "Invalid entry in cache map");
  137. return;
  138. case QSqlTableModelPrivate::Update:
  139. case QSqlTableModelPrivate::Delete:
  140. cache.remove(row);
  141. emit q->dataChanged(q->createIndex(row, 0),
  142. q->createIndex(row, q->columnCount() - 1));
  143. break;
  144. case QSqlTableModelPrivate::Insert: {
  145. QMap<int, QSqlTableModelPrivate::ModifiedRow>::Iterator it = cache.find(row);
  146. if (it == cache.end())
  147. return;
  148. q->beginRemoveRows(QModelIndex(), row, row);
  149. it = cache.erase(it);
  150. while (it != cache.end()) {
  151. int oldKey = it.key();
  152. const QSqlTableModelPrivate::ModifiedRow oldValue = it.value();
  153. cache.erase(it);
  154. it = cache.insert(oldKey - 1, oldValue);
  155. ++it;
  156. }
  157. q->endRemoveRows();
  158. break; }
  159. }
  160. }
  161. bool QSqlTableModelPrivate::exec(const QString &stmt, bool prepStatement,
  162. const QSqlRecord &rec, const QSqlRecord &whereValues)
  163. {
  164. if (stmt.isEmpty())
  165. return false;
  166. // lazy initialization of editQuery
  167. if (editQuery.driver() != db.driver())
  168. editQuery = QSqlQuery(db);
  169. // workaround for In-Process databases - remove all read locks
  170. // from the table to make sure the editQuery succeeds
  171. if (db.driver()->hasFeature(QSqlDriver::SimpleLocking))
  172. const_cast<QSqlResult *>(query.result())->detachFromResultSet();
  173. if (prepStatement) {
  174. if (editQuery.lastQuery() != stmt) {
  175. if (!editQuery.prepare(stmt)) {
  176. error = editQuery.lastError();
  177. return false;
  178. }
  179. }
  180. int i;
  181. for (i = 0; i < rec.count(); ++i) {
  182. if (rec.isGenerated(i) && rec.value(i).type() != QVariant::Invalid)
  183. editQuery.addBindValue(rec.value(i));
  184. }
  185. for (i = 0; i < whereValues.count(); ++i) {
  186. if (whereValues.isGenerated(i) && !whereValues.isNull(i))
  187. editQuery.addBindValue(whereValues.value(i));
  188. }
  189. if (!editQuery.exec()) {
  190. error = editQuery.lastError();
  191. return false;
  192. }
  193. } else {
  194. if (!editQuery.exec(stmt)) {
  195. error = editQuery.lastError();
  196. return false;
  197. }
  198. }
  199. return true;
  200. }
  201. QSqlRecord QSqlTableModelPrivate::primaryValues(int row)
  202. {
  203. QSqlRecord record;
  204. if (!query.seek(row)) {
  205. error = query.lastError();
  206. return record;
  207. }
  208. if (primaryIndex.isEmpty()) {
  209. record = rec;
  210. for (int i = 0; i < record.count(); ++i)
  211. record.setValue(i, query.value(i));
  212. } else {
  213. record = primaryIndex;
  214. for (int i = 0; i < record.count(); ++i)
  215. record.setValue(i, query.value(rec.indexOf(record.fieldName(i))));
  216. }
  217. return record;
  218. }
  219. /*!
  220. \class QSqlTableModel
  221. \brief The QSqlTableModel class provides an editable data model
  222. for a single database table.
  223. \ingroup database
  224. \inmodule QtSql
  225. QSqlTableModel is a high-level interface for reading and writing
  226. database records from a single table. It is build on top of the
  227. lower-level QSqlQuery and can be used to provide data to view
  228. classes such as QTableView. For example:
  229. \snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 24
  230. We set the SQL table's name and the edit strategy, then we set up
  231. the labels displayed in the view header. The edit strategy
  232. dictates when the changes done by the user in the view are
  233. actually applied to the database. The possible values are \l
  234. OnFieldChange, \l OnRowChange, and \l OnManualSubmit.
  235. QSqlTableModel can also be used to access a database
  236. programmatically, without binding it to a view:
  237. \snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 25
  238. The code snippet above extracts the \c salary field from record 4 in
  239. the result set of the query \c{SELECT * from employee}.
  240. It is possible to set filters using setFilter(), or modify the
  241. sort order using setSort(). At the end, you must call select() to
  242. populate the model with data.
  243. The \l{sql/tablemodel} example illustrates how to use
  244. QSqlTableModel as the data source for a QTableView.
  245. QSqlTableModel provides no direct support for foreign keys. Use
  246. the QSqlRelationalTableModel and QSqlRelationalDelegate if you
  247. want to resolve foreign keys.
  248. \sa QSqlRelationalTableModel, QSqlQuery, {Model/View Programming},
  249. {Table Model Example}, {Cached Table Example}
  250. */
  251. /*!
  252. \fn QSqlTableModel::beforeDelete(int row)
  253. This signal is emitted by deleteRowFromTable() before the \a row
  254. is deleted from the currently active database table.
  255. */
  256. /*!
  257. \fn void QSqlTableModel::primeInsert(int row, QSqlRecord &record)
  258. This signal is emitted by insertRows(), when an insertion is
  259. initiated in the given \a row of the currently active database
  260. table. The \a record parameter can be written to (since it is a
  261. reference), for example to populate some fields with default
  262. values.
  263. */
  264. /*!
  265. \fn QSqlTableModel::beforeInsert(QSqlRecord &record)
  266. This signal is emitted by insertRowIntoTable() before a new row is
  267. inserted into the currently active database table. The values that
  268. are about to be inserted are stored in \a record and can be
  269. modified before they will be inserted.
  270. */
  271. /*!
  272. \fn QSqlTableModel::beforeUpdate(int row, QSqlRecord &record)
  273. This signal is emitted by updateRowInTable() before the \a row is
  274. updated in the currently active database table with the values
  275. from \a record.
  276. Note that only values that are marked as generated will be updated.
  277. The generated flag can be set with \l QSqlRecord::setGenerated()
  278. and checked with \l QSqlRecord::isGenerated().
  279. \sa QSqlRecord::isGenerated()
  280. */
  281. /*!
  282. Creates an empty QSqlTableModel and sets the parent to \a parent
  283. and the database connection to \a db. If \a db is not valid, the
  284. default database connection will be used.
  285. The default edit strategy is \l OnRowChange.
  286. */
  287. QSqlTableModel::QSqlTableModel(QObject *parent, QSqlDatabase db)
  288. : QSqlQueryModel(*new QSqlTableModelPrivate, parent)
  289. {
  290. Q_D(QSqlTableModel);
  291. d->db = db.isValid() ? db : QSqlDatabase::database();
  292. }
  293. /*! \internal
  294. */
  295. QSqlTableModel::QSqlTableModel(QSqlTableModelPrivate &dd, QObject *parent, QSqlDatabase db)
  296. : QSqlQueryModel(dd, parent)
  297. {
  298. Q_D(QSqlTableModel);
  299. d->db = db.isValid() ? db : QSqlDatabase::database();
  300. }
  301. /*!
  302. Destroys the object and frees any allocated resources.
  303. */
  304. QSqlTableModel::~QSqlTableModel()
  305. {
  306. }
  307. /*!
  308. Sets the database table on which the model operates to \a
  309. tableName. Does not select data from the table, but fetches its
  310. field information.
  311. To populate the model with the table's data, call select().
  312. Error information can be retrieved with \l lastError().
  313. \sa select(), setFilter(), lastError()
  314. */
  315. void QSqlTableModel::setTable(const QString &tableName)
  316. {
  317. Q_D(QSqlTableModel);
  318. clear();
  319. d->tableName = tableName;
  320. d->initRecordAndPrimaryIndex();
  321. d->initColOffsets(d->rec.count());
  322. if (d->rec.count() == 0)
  323. d->error = QSqlError(QLatin1String("Unable to find table ") + d->tableName, QString(),
  324. QSqlError::StatementError);
  325. }
  326. /*!
  327. Returns the name of the currently selected table.
  328. */
  329. QString QSqlTableModel::tableName() const
  330. {
  331. Q_D(const QSqlTableModel);
  332. return d->tableName;
  333. }
  334. /*!
  335. Populates the model with data from the table that was set via setTable(), using the
  336. specified filter and sort condition, and returns true if successful; otherwise
  337. returns false.
  338. \sa setTable(), setFilter(), selectStatement()
  339. */
  340. bool QSqlTableModel::select()
  341. {
  342. Q_D(QSqlTableModel);
  343. QString query = selectStatement();
  344. if (query.isEmpty())
  345. return false;
  346. revertAll();
  347. QSqlQuery qu(query, d->db);
  348. setQuery(qu);
  349. if (!qu.isActive() || lastError().isValid()) {
  350. // something went wrong - revert to non-select state
  351. d->initRecordAndPrimaryIndex();
  352. return false;
  353. }
  354. return true;
  355. }
  356. /*!
  357. \reimp
  358. */
  359. QVariant QSqlTableModel::data(const QModelIndex &index, int role) const
  360. {
  361. Q_D(const QSqlTableModel);
  362. if (!index.isValid() || (role != Qt::DisplayRole && role != Qt::EditRole))
  363. return QVariant();
  364. QModelIndex item = indexInQuery(index);
  365. switch (d->strategy) {
  366. case OnFieldChange:
  367. case OnRowChange:
  368. if (index.row() == d->insertIndex) {
  369. QVariant val;
  370. if (item.column() < 0 || item.column() >= d->rec.count())
  371. return val;
  372. val = d->editBuffer.value(index.column());
  373. if (val.type() == QVariant::Invalid)
  374. val = QVariant(d->rec.field(item.column()).type());
  375. return val;
  376. }
  377. if (d->editIndex == item.row()) {
  378. QVariant var = d->editBuffer.value(item.column());
  379. if (var.isValid())
  380. return var;
  381. }
  382. break;
  383. case OnManualSubmit: {
  384. const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row());
  385. const QVariant var = row.rec.value(item.column());
  386. if (var.isValid() || row.op == QSqlTableModelPrivate::Insert)
  387. return var;
  388. break; }
  389. }
  390. return QSqlQueryModel::data(item, role);
  391. }
  392. /*!
  393. \reimp
  394. */
  395. QVariant QSqlTableModel::headerData(int section, Qt::Orientation orientation, int role) const
  396. {
  397. Q_D(const QSqlTableModel);
  398. if (orientation == Qt::Vertical && role == Qt::DisplayRole) {
  399. switch (d->strategy) {
  400. case OnFieldChange:
  401. case OnRowChange:
  402. if (d->insertIndex == section)
  403. return QLatin1String("*");
  404. break;
  405. case OnManualSubmit:
  406. QSqlTableModelPrivate::Op op = d->cache.value(section).op;
  407. if (op == QSqlTableModelPrivate::Insert)
  408. return QLatin1String("*");
  409. else if (op == QSqlTableModelPrivate::Delete)
  410. return QLatin1String("!");
  411. break;
  412. }
  413. }
  414. return QSqlQueryModel::headerData(section, orientation, role);
  415. }
  416. /*!
  417. Returns true if the value at the index \a index is dirty, otherwise false.
  418. Dirty values are values that were modified in the model
  419. but not yet written into the database.
  420. If \a index is invalid or points to a non-existing row, false is returned.
  421. */
  422. bool QSqlTableModel::isDirty(const QModelIndex &index) const
  423. {
  424. Q_D(const QSqlTableModel);
  425. if (!index.isValid())
  426. return false;
  427. switch (d->strategy) {
  428. case OnFieldChange:
  429. return false;
  430. case OnRowChange:
  431. return index.row() == d->editIndex && d->editBuffer.value(index.column()).isValid();
  432. case OnManualSubmit: {
  433. const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row());
  434. return row.op == QSqlTableModelPrivate::Insert
  435. || row.op == QSqlTableModelPrivate::Delete
  436. || (row.op == QSqlTableModelPrivate::Update
  437. && row.rec.value(index.column()).isValid());
  438. }
  439. }
  440. return false;
  441. }
  442. /*!
  443. Sets the data for the item \a index for the role \a role to \a
  444. value. Depending on the edit strategy, the value might be applied
  445. to the database at once or cached in the model.
  446. Returns true if the value could be set or false on error, for
  447. example if \a index is out of bounds.
  448. \sa editStrategy(), data(), submit(), submitAll(), revertRow()
  449. */
  450. bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
  451. {
  452. Q_D(QSqlTableModel);
  453. if (role != Qt::EditRole)
  454. return QSqlQueryModel::setData(index, value, role);
  455. if (!index.isValid() || index.column() >= d->rec.count() || index.row() >= rowCount())
  456. return false;
  457. bool isOk = true;
  458. switch (d->strategy) {
  459. case OnFieldChange: {
  460. if (index.row() == d->insertIndex) {
  461. d->editBuffer.setValue(index.column(), value);
  462. return true;
  463. }
  464. d->clearEditBuffer();
  465. d->editBuffer.setValue(index.column(), value);
  466. isOk = updateRowInTable(index.row(), d->editBuffer);
  467. if (isOk)
  468. select();
  469. emit dataChanged(index, index);
  470. break; }
  471. case OnRowChange:
  472. if (index.row() == d->insertIndex) {
  473. d->editBuffer.setValue(index.column(), value);
  474. return true;
  475. }
  476. if (d->editIndex != index.row()) {
  477. if (d->editIndex != -1)
  478. submit();
  479. d->clearEditBuffer();
  480. }
  481. d->editBuffer.setValue(index.column(), value);
  482. d->editIndex = index.row();
  483. emit dataChanged(index, index);
  484. break;
  485. case OnManualSubmit: {
  486. QSqlTableModelPrivate::ModifiedRow &row = d->cache[index.row()];
  487. if (row.op == QSqlTableModelPrivate::None) {
  488. row.op = QSqlTableModelPrivate::Update;
  489. row.rec = d->rec;
  490. row.primaryValues = d->primaryValues(indexInQuery(index).row());
  491. }
  492. row.rec.setValue(index.column(), value);
  493. emit dataChanged(index, index);
  494. break; }
  495. }
  496. return isOk;
  497. }
  498. /*!
  499. This function simply calls QSqlQueryModel::setQuery(\a query).
  500. You should normally not call it on a QSqlTableModel. Instead, use
  501. setTable(), setSort(), setFilter(), etc., to set up the query.
  502. \sa selectStatement()
  503. */
  504. void QSqlTableModel::setQuery(const QSqlQuery &query)
  505. {
  506. QSqlQueryModel::setQuery(query);
  507. }
  508. /*!
  509. Updates the given \a row in the currently active database table
  510. with the specified \a values. Returns true if successful; otherwise
  511. returns false.
  512. This is a low-level method that operates directly on the database
  513. and should not be called directly. Use setData() to update values.
  514. The model will decide depending on its edit strategy when to modify
  515. the database.
  516. Note that only values that have the generated-flag set are updated.
  517. The generated-flag can be set with QSqlRecord::setGenerated() and
  518. tested with QSqlRecord::isGenerated().
  519. \sa QSqlRecord::isGenerated(), setData()
  520. */
  521. bool QSqlTableModel::updateRowInTable(int row, const QSqlRecord &values)
  522. {
  523. Q_D(QSqlTableModel);
  524. QSqlRecord rec(values);
  525. emit beforeUpdate(row, rec);
  526. const QSqlRecord whereValues = d->strategy == OnManualSubmit ? d->cache[row].primaryValues : d->primaryValues(row);
  527. bool prepStatement = d->db.driver()->hasFeature(QSqlDriver::PreparedQueries);
  528. QString stmt = d->db.driver()->sqlStatement(QSqlDriver::UpdateStatement, d->tableName,
  529. rec, prepStatement);
  530. QString where = d->db.driver()->sqlStatement(QSqlDriver::WhereStatement, d->tableName,
  531. whereValues, prepStatement);
  532. if (stmt.isEmpty() || where.isEmpty() || row < 0 || row >= rowCount()) {
  533. d->error = QSqlError(QLatin1String("No Fields to update"), QString(),
  534. QSqlError::StatementError);
  535. return false;
  536. }
  537. stmt.append(QLatin1Char(' ')).append(where);
  538. return d->exec(stmt, prepStatement, rec, whereValues);
  539. }
  540. /*!
  541. Inserts the values \a values into the currently active database table.
  542. This is a low-level method that operates directly on the database
  543. and should not be called directly. Use insertRow() and setData()
  544. to insert values. The model will decide depending on its edit strategy
  545. when to modify the database.
  546. Returns true if the values could be inserted, otherwise false.
  547. Error information can be retrieved with \l lastError().
  548. \sa lastError(), insertRow(), insertRows()
  549. */
  550. bool QSqlTableModel::insertRowIntoTable(const QSqlRecord &values)
  551. {
  552. Q_D(QSqlTableModel);
  553. QSqlRecord rec = values;
  554. emit beforeInsert(rec);
  555. bool prepStatement = d->db.driver()->hasFeature(QSqlDriver::PreparedQueries);
  556. QString stmt = d->db.driver()->sqlStatement(QSqlDriver::InsertStatement, d->tableName,
  557. rec, prepStatement);
  558. if (stmt.isEmpty()) {
  559. d->error = QSqlError(QLatin1String("No Fields to update"), QString(),
  560. QSqlError::StatementError);
  561. return false;
  562. }
  563. return d->exec(stmt, prepStatement, rec);
  564. }
  565. /*!
  566. Deletes the given \a row from the currently active database table.
  567. This is a low-level method that operates directly on the database
  568. and should not be called directly. Use removeRow() or removeRows()
  569. to delete values. The model will decide depending on its edit strategy
  570. when to modify the database.
  571. Returns true if the row was deleted; otherwise returns false.
  572. \sa removeRow(), removeRows()
  573. */
  574. bool QSqlTableModel::deleteRowFromTable(int row)
  575. {
  576. Q_D(QSqlTableModel);
  577. emit beforeDelete(row);
  578. const QSqlRecord whereValues = d->strategy == OnManualSubmit ? d->cache[row].primaryValues : d->primaryValues(row);
  579. bool prepStatement = d->db.driver()->hasFeature(QSqlDriver::PreparedQueries);
  580. QString stmt = d->db.driver()->sqlStatement(QSqlDriver::DeleteStatement,
  581. d->tableName,
  582. QSqlRecord(),
  583. prepStatement);
  584. QString where = d->db.driver()->sqlStatement(QSqlDriver::WhereStatement,
  585. d->tableName,
  586. whereValues,
  587. prepStatement);
  588. if (stmt.isEmpty() || where.isEmpty()) {
  589. d->error = QSqlError(QLatin1String("Unable to delete row"), QString(),
  590. QSqlError::StatementError);
  591. return false;
  592. }
  593. stmt.append(QLatin1Char(' ')).append(where);
  594. return d->exec(stmt, prepStatement, whereValues);
  595. }
  596. /*!
  597. Submits all pending changes and returns true on success.
  598. Returns false on error, detailed error information can be
  599. obtained with lastError().
  600. On success the model will be repopulated. Any views
  601. presenting it will lose their selections.
  602. Note: In OnManualSubmit mode, already submitted changes won't
  603. be cleared from the cache when submitAll() fails. This allows
  604. transactions to be rolled back and resubmitted again without
  605. losing data.
  606. \sa revertAll(), lastError()
  607. */
  608. bool QSqlTableModel::submitAll()
  609. {
  610. Q_D(QSqlTableModel);
  611. switch (d->strategy) {
  612. case OnFieldChange:
  613. if (d->insertIndex == -1)
  614. return true;
  615. // else fall through
  616. case OnRowChange:
  617. if (d->editBuffer.isEmpty())
  618. return true;
  619. if (d->insertIndex != -1) {
  620. if (!insertRowIntoTable(d->editBuffer))
  621. return false;
  622. d->bottom = d->bottom.sibling(d->bottom.row() + 1, d->bottom.column());
  623. } else {
  624. if (!updateRowInTable(d->editIndex, d->editBuffer))
  625. return false;
  626. }
  627. d->clearEditBuffer();
  628. d->editIndex = -1;
  629. d->insertIndex = -1;
  630. return select();
  631. case OnManualSubmit:
  632. for (QSqlTableModelPrivate::CacheMap::ConstIterator it = d->cache.constBegin();
  633. it != d->cache.constEnd(); ++it) {
  634. switch (it.value().op) {
  635. case QSqlTableModelPrivate::Insert:
  636. if (!insertRowIntoTable(it.value().rec))
  637. return false;
  638. d->bottom = d->bottom.sibling(d->bottom.row() + 1, d->bottom.column());
  639. break;
  640. case QSqlTableModelPrivate::Update:
  641. if (!updateRowInTable(it.key(), it.value().rec))
  642. return false;
  643. break;
  644. case QSqlTableModelPrivate::Delete:
  645. if (!deleteRowFromTable(it.key()))
  646. return false;
  647. break;
  648. case QSqlTableModelPrivate::None:
  649. Q_ASSERT_X(false, "QSqlTableModel::submitAll()", "Invalid cache operation");
  650. break;
  651. }
  652. }
  653. d->clearCache();
  654. return select();
  655. }
  656. return false;
  657. }
  658. /*!
  659. This reimplemented slot is called by the item delegates when the
  660. user stopped editing the current row.
  661. Submits the currently edited row if the model's strategy is set
  662. to OnRowChange or OnFieldChange. Does nothing for the OnManualSubmit
  663. strategy.
  664. Use submitAll() to submit all pending changes for the
  665. OnManualSubmit strategy.
  666. Returns true on success; otherwise returns false. Use lastError()
  667. to query detailed error information.
  668. On success the model will be repopulated. Any views
  669. presenting it will lose their selections.
  670. \sa revert(), revertRow(), submitAll(), revertAll(), lastError()
  671. */
  672. bool QSqlTableModel::submit()
  673. {
  674. Q_D(QSqlTableModel);
  675. if (d->strategy == OnRowChange || d->strategy == OnFieldChange)
  676. return submitAll();
  677. return true;
  678. }
  679. /*!
  680. This reimplemented slot is called by the item delegates when the
  681. user canceled editing the current row.
  682. Reverts the changes if the model's strategy is set to
  683. OnRowChange. Does nothing for the other edit strategies.
  684. Use revertAll() to revert all pending changes for the
  685. OnManualSubmit strategy or revertRow() to revert a specific row.
  686. \sa submit(), submitAll(), revertRow(), revertAll()
  687. */
  688. void QSqlTableModel::revert()
  689. {
  690. Q_D(QSqlTableModel);
  691. if (d->strategy == OnRowChange)
  692. revertAll();
  693. }
  694. /*!
  695. \enum QSqlTableModel::EditStrategy
  696. This enum type describes which strategy to choose when editing values in the database.
  697. \value OnFieldChange All changes to the model will be applied immediately to the database.
  698. \value OnRowChange Changes to a row will be applied when the user selects a different row.
  699. \value OnManualSubmit All changes will be cached in the model until either submitAll()
  700. or revertAll() is called.
  701. Note: To prevent inserting only partly initialized rows into the database,
  702. \c OnFieldChange will behave like \c OnRowChange for newly inserted rows.
  703. \sa setEditStrategy()
  704. */
  705. /*!
  706. Sets the strategy for editing values in the database to \a
  707. strategy.
  708. This will revert any pending changes.
  709. \sa editStrategy(), revertAll()
  710. */
  711. void QSqlTableModel::setEditStrategy(EditStrategy strategy)
  712. {
  713. Q_D(QSqlTableModel);
  714. revertAll();
  715. d->strategy = strategy;
  716. }
  717. /*!
  718. Returns the current edit strategy.
  719. \sa setEditStrategy()
  720. */
  721. QSqlTableModel::EditStrategy QSqlTableModel::editStrategy() const
  722. {
  723. Q_D(const QSqlTableModel);
  724. return d->strategy;
  725. }
  726. /*!
  727. Reverts all pending changes.
  728. \sa revert(), revertRow(), submitAll()
  729. */
  730. void QSqlTableModel::revertAll()
  731. {
  732. Q_D(QSqlTableModel);
  733. switch (d->strategy) {
  734. case OnFieldChange:
  735. break;
  736. case OnRowChange:
  737. if (d->editIndex != -1)
  738. revertRow(d->editIndex);
  739. else if (d->insertIndex != -1)
  740. revertRow(d->insertIndex);
  741. break;
  742. case OnManualSubmit:
  743. while (!d->cache.isEmpty())
  744. revertRow(d->cache.constBegin().key());
  745. break;
  746. }
  747. }
  748. /*!
  749. Reverts all changes for the specified \a row.
  750. \sa revert(), revertAll(), submit(), submitAll()
  751. */
  752. void QSqlTableModel::revertRow(int row)
  753. {
  754. if (row < 0)
  755. return;
  756. Q_D(QSqlTableModel);
  757. switch (d->strategy) {
  758. case OnFieldChange:
  759. break;
  760. case OnRowChange: {
  761. if (d->editIndex == row) {
  762. d->editBuffer.clear();
  763. int oldIndex = d->editIndex;
  764. d->editIndex = -1;
  765. emit dataChanged(createIndex(oldIndex, 0), createIndex(oldIndex, columnCount()));
  766. } else if (d->insertIndex == row) {
  767. d->revertInsertedRow();
  768. }
  769. break; }
  770. case OnManualSubmit:
  771. d->revertCachedRow(row);
  772. break;
  773. }
  774. }
  775. /*!
  776. Returns the primary key for the current table, or an empty
  777. QSqlIndex if the table is not set or has no primary key.
  778. \sa setTable(), setPrimaryKey(), QSqlDatabase::primaryIndex()
  779. */
  780. QSqlIndex QSqlTableModel::primaryKey() const
  781. {
  782. Q_D(const QSqlTableModel);
  783. return d->primaryIndex;
  784. }
  785. /*!
  786. Protected method that allows subclasses to set the primary key to
  787. \a key.
  788. Normally, the primary index is set automatically whenever you
  789. call setTable().
  790. \sa primaryKey(), QSqlDatabase::primaryIndex()
  791. */
  792. void QSqlTableModel::setPrimaryKey(const QSqlIndex &key)
  793. {
  794. Q_D(QSqlTableModel);
  795. d->primaryIndex = key;
  796. }
  797. /*!
  798. Returns a pointer to the used QSqlDatabase or 0 if no database was set.
  799. */
  800. QSqlDatabase QSqlTableModel::database() const
  801. {
  802. Q_D(const QSqlTableModel);
  803. return d->db;
  804. }
  805. /*!
  806. Sorts the data by \a column with the sort order \a order.
  807. This will immediately select data, use setSort()
  808. to set a sort order without populating the model with data.
  809. \sa setSort(), select(), orderByClause()
  810. */
  811. void QSqlTableModel::sort(int column, Qt::SortOrder order)
  812. {
  813. setSort(column, order);
  814. select();
  815. }
  816. /*!
  817. Sets the sort order for \a column to \a order. This does not
  818. affect the current data, to refresh the data using the new
  819. sort order, call select().
  820. \sa select(), orderByClause()
  821. */
  822. void QSqlTableModel::setSort(int column, Qt::SortOrder order)
  823. {
  824. Q_D(QSqlTableModel);
  825. d->sortColumn = column;
  826. d->sortOrder = order;
  827. }
  828. /*!
  829. Returns an SQL \c{ORDER BY} clause based on the currently set
  830. sort order.
  831. \sa setSort(), selectStatement()
  832. */
  833. QString QSqlTableModel::orderByClause() const
  834. {
  835. Q_D(const QSqlTableModel);
  836. QString s;
  837. QSqlField f = d->rec.field(d->sortColumn);
  838. if (!f.isValid())
  839. return s;
  840. QString table = d->tableName;
  841. //we can safely escape the field because it would have been obtained from the database
  842. //and have the correct case
  843. QString field = d->db.driver()->escapeIdentifier(f.name(), QSqlDriver::FieldName);
  844. s.append(QLatin1String("ORDER BY ")).append(table).append(QLatin1Char('.')).append(field);
  845. s += d->sortOrder == Qt::AscendingOrder ? QLatin1String(" ASC") : QLatin1String(" DESC");
  846. return s;
  847. }
  848. /*!
  849. Returns the index of the field \a fieldName.
  850. */
  851. int QSqlTableModel::fieldIndex(const QString &fieldName) const
  852. {
  853. Q_D(const QSqlTableModel);
  854. return d->rec.indexOf(fieldName);
  855. }
  856. /*!
  857. Returns the SQL \c SELECT statement used internally to populate
  858. the model. The statement includes the filter and the \c{ORDER BY}
  859. clause.
  860. \sa filter(), orderByClause()
  861. */
  862. QString QSqlTableModel::selectStatement() const
  863. {
  864. Q_D(const QSqlTableModel);
  865. QString query;
  866. if (d->tableName.isEmpty()) {
  867. d->error = QSqlError(QLatin1String("No table name given"), QString(),
  868. QSqlError::StatementError);
  869. return query;
  870. }
  871. if (d->rec.isEmpty()) {
  872. d->error = QSqlError(QLatin1String("Unable to find table ") + d->tableName, QString(),
  873. QSqlError::StatementError);
  874. return query;
  875. }
  876. query = d->db.driver()->sqlStatement(QSqlDriver::SelectStatement,
  877. d->tableName,
  878. d->rec,
  879. false);
  880. if (query.isEmpty()) {
  881. d->error = QSqlError(QLatin1String("Unable to select fields from table ") + d->tableName,
  882. QString(), QSqlError::StatementError);
  883. return query;
  884. }
  885. if (!d->filter.isEmpty())
  886. query.append(QLatin1String(" WHERE ")).append(d->filter);
  887. QString orderBy(orderByClause());
  888. if (!orderBy.isEmpty())
  889. query.append(QLatin1Char(' ')).append(orderBy);
  890. return query;
  891. }
  892. /*!
  893. Removes \a count columns from the \a parent model, starting at
  894. index \a column.
  895. Returns if the columns were successfully removed; otherwise
  896. returns false.
  897. \sa removeRows()
  898. */
  899. bool QSqlTableModel::removeColumns(int column, int count, const QModelIndex &parent)
  900. {
  901. Q_D(QSqlTableModel);
  902. if (parent.isValid() || column < 0 || column + count > d->rec.count())
  903. return false;
  904. for (int i = 0; i < count; ++i)
  905. d->rec.remove(column);
  906. if (d->query.isActive())
  907. return select();
  908. return true;
  909. }
  910. /*!
  911. Removes \a count rows starting at \a row. Since this model
  912. does not support hierarchical structures, \a parent must be
  913. an invalid model index.
  914. Emits the beforeDelete() signal before a row is deleted. When
  915. the edit strategy is OnManualSubmit signal emission is delayed
  916. until submitAll() is called.
  917. Returns true if all rows could be removed; otherwise returns
  918. false. Detailed error information can be retrieved using
  919. lastError().
  920. \sa removeColumns(), insertRows()
  921. */
  922. bool QSqlTableModel::removeRows(int row, int count, const QModelIndex &parent)
  923. {
  924. Q_D(QSqlTableModel);
  925. if (parent.isValid() || row < 0 || count <= 0)
  926. return false;
  927. int i;
  928. switch (d->strategy) {
  929. case OnFieldChange:
  930. case OnRowChange:
  931. for (i = 0; i < count; ++i) {
  932. if (row + i == d->insertIndex)
  933. d->revertInsertedRow();
  934. else if (!deleteRowFromTable(row + i))
  935. return false;
  936. }
  937. select();
  938. break;
  939. case OnManualSubmit:
  940. for (i = 0; i < count; ++i) {
  941. int idx = row + i;
  942. if (idx >= rowCount())
  943. return false;
  944. if (d->cache.value(idx).op == QSqlTableModelPrivate::Insert)
  945. revertRow(idx);
  946. else {
  947. d->cache[idx].op = QSqlTableModelPrivate::Delete;
  948. d->cache[idx].primaryValues = d->primaryValues(indexInQuery(createIndex(idx, 0)).row());
  949. emit headerDataChanged(Qt::Vertical, idx, idx);
  950. }
  951. }
  952. break;
  953. }
  954. return true;
  955. }
  956. /*!
  957. Inserts \a count empty rows at position \a row. Note that \a
  958. parent must be invalid, since this model does not support
  959. parent-child relations.
  960. Only one row at a time can be inserted when using the
  961. OnFieldChange or OnRowChange update strategies.
  962. The primeInsert() signal will be emitted for each new row.
  963. Connect to it if you want to initialize the new row with default
  964. values.
  965. Returns false if the parameters are out of bounds; otherwise
  966. returns true.
  967. \sa primeInsert(), insertRecord()
  968. */
  969. bool QSqlTableModel::insertRows(int row, int count, const QModelIndex &parent)
  970. {
  971. Q_D(QSqlTableModel);
  972. if (row < 0 || count <= 0 || row > rowCount() || parent.isValid())
  973. return false;
  974. switch (d->strategy) {
  975. case OnFieldChange:
  976. case OnRowChange:
  977. if (count != 1)
  978. return false;
  979. beginInsertRows(parent, row, row);
  980. d->insertIndex = row;
  981. // ### apply dangling changes...
  982. d->clearEditBuffer();
  983. emit primeInsert(row, d->editBuffer);
  984. break;
  985. case OnManualSubmit:
  986. beginInsertRows(parent, row, row + count - 1);
  987. if (!d->cache.isEmpty()) {
  988. QMap<int, QSqlTableModelPrivate::ModifiedRow>::Iterator it = d->cache.end();
  989. while (it != d->cache.begin() && (--it).key() >= row) {
  990. int oldKey = it.key();
  991. const QSqlTableModelPrivate::ModifiedRow oldValue = it.value();
  992. d->cache.erase(it);
  993. it = d->cache.insert(oldKey + count, oldValue);
  994. }
  995. }
  996. for (int i = 0; i < count; ++i) {
  997. d->cache[row + i] = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Insert,
  998. d->rec);
  999. emit primeInsert(row + i, d->cache[row + i].rec);
  1000. }
  1001. break;
  1002. }
  1003. endInsertRows();
  1004. return true;
  1005. }
  1006. /*!
  1007. Inserts the \a record after \a row. If \a row is negative, the
  1008. record will be appended to the end. Calls insertRows() and
  1009. setRecord() internally.
  1010. Returns true if the row could be inserted, otherwise false.
  1011. \sa insertRows(), removeRows()
  1012. */
  1013. bool QSqlTableModel::insertRecord(int row, const QSqlRecord &record)
  1014. {
  1015. Q_D(QSqlTableModel);
  1016. if (row < 0)
  1017. row = rowCount();
  1018. if (!insertRow(row, QModelIndex()))
  1019. return false;
  1020. if (!setRecord(row, record))
  1021. return false;
  1022. if (d->strategy == OnFieldChange || d->strategy == OnRowChange)
  1023. return submit();
  1024. return true;
  1025. }
  1026. /*! \reimp
  1027. */
  1028. int QSqlTableModel::rowCount(const QModelIndex &parent) const
  1029. {
  1030. Q_D(const QSqlTableModel);
  1031. if (parent.isValid())
  1032. return 0;
  1033. int rc = QSqlQueryModel::rowCount();
  1034. if (d->strategy == OnManualSubmit) {
  1035. for (QSqlTableModelPrivate::CacheMap::ConstIterator it = d->cache.constBegin();
  1036. it != d->cache.constEnd(); ++it) {
  1037. if (it.value().op == QSqlTableModelPrivate::Insert)
  1038. ++rc;
  1039. }
  1040. } else if (d->insertIndex >= 0) {
  1041. ++rc;
  1042. }
  1043. return rc;
  1044. }
  1045. /*!
  1046. Returns the index of the value in the database result set for the
  1047. given \a item in the model.
  1048. The return value is identical to \a item if no columns or rows
  1049. have been inserted, removed, or moved around.
  1050. Returns an invalid model index if \a item is out of bounds or if
  1051. \a item does not point to a value in the result set.
  1052. \sa QSqlQueryModel::indexInQuery()
  1053. */
  1054. QModelIndex QSqlTableModel::indexInQuery(const QModelIndex &item) const
  1055. {
  1056. Q_D(const QSqlTableModel);
  1057. const QModelIndex it = QSqlQueryModel::indexInQuery(item);
  1058. if (d->strategy == OnManualSubmit) {
  1059. int rowOffset = 0;
  1060. QSqlTableModelPrivate::CacheMap::ConstIterator i = d->cache.constBegin();
  1061. while (i != d->cache.constEnd() && i.key() <= it.row()) {
  1062. if (i.value().op == QSqlTableModelPrivate::Insert)
  1063. ++rowOffset;
  1064. ++i;
  1065. }
  1066. return createIndex(it.row() - rowOffset, it.column(), it.internalPointer());
  1067. } else {
  1068. if (d->insertIndex >= 0 && it.row() >= d->insertIndex)
  1069. return createIndex(it.row() - 1, it.column(), it.internalPointer());
  1070. }
  1071. return it;
  1072. }
  1073. /*!
  1074. Returns the currently set filter.
  1075. \sa setFilter(), select()
  1076. */
  1077. QString QSqlTableModel::filter() const
  1078. {
  1079. Q_D(const QSqlTableModel);
  1080. return d->filter;
  1081. }
  1082. /*!
  1083. Sets the current filter to \a filter.
  1084. The filter is a SQL \c WHERE clause without the keyword \c WHERE
  1085. (for example, \c{name='Josephine')}.
  1086. If the model is already populated with data from a database,
  1087. the model re-selects it with the new filter. Otherwise, the filter
  1088. will be applied the next time select() is called.
  1089. \sa filter(), select(), selectStatement(), orderByClause()
  1090. */
  1091. void QSqlTableModel::setFilter(const QString &filter)
  1092. {
  1093. Q_D(QSqlTableModel);
  1094. d->filter = filter;
  1095. if (d->query.isActive())
  1096. select();
  1097. }
  1098. /*! \reimp
  1099. */
  1100. void QSqlTableModel::clear()
  1101. {
  1102. Q_D(QSqlTableModel);
  1103. d->clear();
  1104. QSqlQueryModel::clear();
  1105. }
  1106. /*! \reimp
  1107. */
  1108. Qt::ItemFlags QSqlTableModel::flags(const QModelIndex &index) const
  1109. {
  1110. Q_D(const QSqlTableModel);
  1111. if (index.internalPointer() || index.column() < 0 || index.column() >= d->rec.count()
  1112. || index.row() < 0)
  1113. return 0;
  1114. if (d->rec.field(index.column()).isReadOnly())
  1115. return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
  1116. return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
  1117. }
  1118. /*!
  1119. Sets the values at the specified \a row to the values of \a
  1120. record. Returns true if all the values could be set; otherwise
  1121. returns false.
  1122. \sa record()
  1123. */
  1124. bool QSqlTableModel::setRecord(int row, const QSqlRecord &record)
  1125. {
  1126. Q_D(QSqlTableModel);
  1127. Q_ASSERT_X(row >= 0, "QSqlTableModel::setRecord()", "Cannot set a record to a row less than 0");
  1128. if (row >= rowCount())
  1129. return false;
  1130. bool isOk = true;
  1131. switch (d->strategy) {
  1132. case OnFieldChange:
  1133. case OnRowChange:
  1134. return d->setRecord(row, record);
  1135. case OnManualSubmit: {
  1136. QSqlTableModelPrivate::ModifiedRow &mrow = d->cache[row];
  1137. if (mrow.op == QSqlTableModelPrivate::None) {
  1138. mrow.op = QSqlTableModelPrivate::Update;
  1139. mrow.rec = d->rec;
  1140. mrow.primaryValues = d->primaryValues(indexInQuery(createIndex(row, 0)).row());
  1141. }
  1142. QString fieldName;
  1143. for (int i = 0; i < record.count(); ++i) {
  1144. fieldName = record.fieldName(i);
  1145. if (d->db.driver()->isIdentifierEscaped(fieldName, QSqlDriver::FieldName))
  1146. fieldName = d->db.driver()->stripDelimiters(fieldName, QSqlDriver::FieldName);
  1147. int idx = mrow.rec.indexOf(fieldName);
  1148. if (idx == -1)
  1149. isOk = false;
  1150. else
  1151. mrow.rec.setValue(idx, record.value(i));
  1152. }
  1153. return isOk; }
  1154. }
  1155. return false;
  1156. }
  1157. QT_END_NAMESPACE