1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtSql module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
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.
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.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "qsqltablemodel.h"
44 #include "qsqldriver.h"
45 #include "qsqlerror.h"
46 #include "qsqlfield.h"
47 #include "qsqlindex.h"
48 #include "qsqlquery.h"
49 #include "qsqlrecord.h"
50 #include "qsqlresult.h"
52 #include "qsqltablemodel_p.h"
59 Populates our record with values.
61 QSqlRecord QSqlTableModelPrivate::record(const QVector<QVariant> &values) const
64 for (int i = 0; i < r.count() && i < values.count(); ++i)
65 r.setValue(i, values.at(i));
70 Set a record for OnFieldChange and OnRowChange.
72 bool QSqlTableModelPrivate::setRecord(int row, const QSqlRecord &record)
77 QSqlTableModel::EditStrategy oldStrategy = strategy;
79 // FieldChange strategy makes no sense when setting an entire row
80 if (strategy == QSqlTableModel::OnFieldChange)
81 strategy = QSqlTableModel::OnRowChange;
82 for (int i = 0; i < record.count(); ++i) {
83 int idx = nameToIndex(record.fieldName(i));
86 QModelIndex cIndex = q->createIndex(row, idx);
87 QVariant value = record.value(i);
88 QVariant oldValue = q->data(cIndex);
89 if (oldValue.isNull() || oldValue != value)
90 isOk &= q->setData(cIndex, value, Qt::EditRole);
92 if (isOk && oldStrategy == QSqlTableModel::OnFieldChange)
94 strategy = oldStrategy;
99 int QSqlTableModelPrivate::nameToIndex(const QString &name) const
101 QString fieldname = name;
102 if (db.driver()->isIdentifierEscaped(fieldname, QSqlDriver::FieldName))
103 fieldname = db.driver()->stripDelimiters(fieldname, QSqlDriver::FieldName);
104 return rec.indexOf(fieldname);
107 void QSqlTableModelPrivate::initRecordAndPrimaryIndex()
109 rec = db.record(tableName);
110 primaryIndex = db.primaryIndex(tableName);
113 void QSqlTableModelPrivate::clear()
117 sortOrder = Qt::AscendingOrder;
122 primaryIndex.clear();
127 void QSqlTableModelPrivate::revertInsertedRow()
130 if (insertIndex == -1)
133 q->beginRemoveRows(QModelIndex(), insertIndex, insertIndex);
138 void QSqlTableModelPrivate::clearEditBuffer()
143 void QSqlTableModelPrivate::clearCache()
148 void QSqlTableModelPrivate::revertCachedRow(int row)
151 ModifiedRow r = cache.value(row);
153 case QSqlTableModelPrivate::None:
154 Q_ASSERT_X(false, "QSqlTableModelPrivate::revertCachedRow()", "Invalid entry in cache map");
156 case QSqlTableModelPrivate::Update:
157 case QSqlTableModelPrivate::Delete:
159 emit q->dataChanged(q->createIndex(row, 0),
160 q->createIndex(row, q->columnCount() - 1));
162 case QSqlTableModelPrivate::Insert: {
163 QMap<int, QSqlTableModelPrivate::ModifiedRow>::Iterator it = cache.find(row);
164 if (it == cache.end())
166 q->beginRemoveRows(QModelIndex(), row, row);
167 it = cache.erase(it);
168 while (it != cache.end()) {
169 int oldKey = it.key();
170 const QSqlTableModelPrivate::ModifiedRow oldValue = it.value();
172 it = cache.insert(oldKey - 1, oldValue);
180 bool QSqlTableModelPrivate::exec(const QString &stmt, bool prepStatement,
181 const QSqlRecord &rec, const QSqlRecord &whereValues)
186 // lazy initialization of editQuery
187 if (editQuery.driver() != db.driver())
188 editQuery = QSqlQuery(db);
190 // workaround for In-Process databases - remove all read locks
191 // from the table to make sure the editQuery succeeds
192 if (db.driver()->hasFeature(QSqlDriver::SimpleLocking))
193 const_cast<QSqlResult *>(query.result())->detachFromResultSet();
196 if (editQuery.lastQuery() != stmt) {
197 if (!editQuery.prepare(stmt)) {
198 error = editQuery.lastError();
203 for (i = 0; i < rec.count(); ++i) {
204 if (rec.isGenerated(i) && rec.value(i).type() != QVariant::Invalid)
205 editQuery.addBindValue(rec.value(i));
207 for (i = 0; i < whereValues.count(); ++i) {
208 if (whereValues.isGenerated(i) && !whereValues.isNull(i))
209 editQuery.addBindValue(whereValues.value(i));
212 if (!editQuery.exec()) {
213 error = editQuery.lastError();
217 if (!editQuery.exec(stmt)) {
218 error = editQuery.lastError();
225 QSqlRecord QSqlTableModelPrivate::primaryValues(int row)
228 if (!query.seek(row)) {
229 error = query.lastError();
232 if (primaryIndex.isEmpty()) {
234 for (int i = 0; i < record.count(); ++i)
235 record.setValue(i, query.value(i));
237 record = primaryIndex;
238 for (int i = 0; i < record.count(); ++i)
239 record.setValue(i, query.value(rec.indexOf(record.fieldName(i))));
245 \class QSqlTableModel
246 \brief The QSqlTableModel class provides an editable data model
247 for a single database table.
252 QSqlTableModel is a high-level interface for reading and writing
253 database records from a single table. It is build on top of the
254 lower-level QSqlQuery and can be used to provide data to view
255 classes such as QTableView. For example:
257 \snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 24
259 We set the SQL table's name and the edit strategy, then we set up
260 the labels displayed in the view header. The edit strategy
261 dictates when the changes done by the user in the view are
262 actually applied to the database. The possible values are \l
263 OnFieldChange, \l OnRowChange, and \l OnManualSubmit.
265 QSqlTableModel can also be used to access a database
266 programmatically, without binding it to a view:
268 \snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 21
270 The code snippet above extracts the \c salary field from record 4 in
271 the result set of the query \c{SELECT * from employee}.
273 It is possible to set filters using setFilter(), or modify the
274 sort order using setSort(). At the end, you must call select() to
275 populate the model with data.
277 The \l{sql/tablemodel} example illustrates how to use
278 QSqlTableModel as the data source for a QTableView.
280 QSqlTableModel provides no direct support for foreign keys. Use
281 the QSqlRelationalTableModel and QSqlRelationalDelegate if you
282 want to resolve foreign keys.
284 \sa QSqlRelationalTableModel, QSqlQuery, {Model/View Programming},
285 {Table Model Example}, {Cached Table Example}
289 \fn QSqlTableModel::beforeDelete(int row)
291 This signal is emitted by deleteRowFromTable() before the \a row
292 is deleted from the currently active database table.
296 \fn void QSqlTableModel::primeInsert(int row, QSqlRecord &record)
298 This signal is emitted by insertRows(), when an insertion is
299 initiated in the given \a row of the currently active database
300 table. The \a record parameter can be written to (since it is a
301 reference), for example to populate some fields with default
306 \fn QSqlTableModel::beforeInsert(QSqlRecord &record)
308 This signal is emitted by insertRowIntoTable() before a new row is
309 inserted into the currently active database table. The values that
310 are about to be inserted are stored in \a record and can be
311 modified before they will be inserted.
315 \fn QSqlTableModel::beforeUpdate(int row, QSqlRecord &record)
317 This signal is emitted by updateRowInTable() before the \a row is
318 updated in the currently active database table with the values
321 Note that only values that are marked as generated will be updated.
322 The generated flag can be set with \l QSqlRecord::setGenerated()
323 and checked with \l QSqlRecord::isGenerated().
325 \sa QSqlRecord::isGenerated()
329 Creates an empty QSqlTableModel and sets the parent to \a parent
330 and the database connection to \a db. If \a db is not valid, the
331 default database connection will be used.
333 The default edit strategy is \l OnRowChange.
335 QSqlTableModel::QSqlTableModel(QObject *parent, QSqlDatabase db)
336 : QSqlQueryModel(*new QSqlTableModelPrivate, parent)
339 d->db = db.isValid() ? db : QSqlDatabase::database();
344 QSqlTableModel::QSqlTableModel(QSqlTableModelPrivate &dd, QObject *parent, QSqlDatabase db)
345 : QSqlQueryModel(dd, parent)
348 d->db = db.isValid() ? db : QSqlDatabase::database();
352 Destroys the object and frees any allocated resources.
354 QSqlTableModel::~QSqlTableModel()
359 Sets the database table on which the model operates to \a
360 tableName. Does not select data from the table, but fetches its
363 To populate the model with the table's data, call select().
365 Error information can be retrieved with \l lastError().
367 \sa select(), setFilter(), lastError()
369 void QSqlTableModel::setTable(const QString &tableName)
373 d->tableName = tableName;
374 d->initRecordAndPrimaryIndex();
375 d->initColOffsets(d->rec.count());
377 if (d->rec.count() == 0)
378 d->error = QSqlError(QLatin1String("Unable to find table ") + d->tableName, QString(),
379 QSqlError::StatementError);
383 Returns the name of the currently selected table.
385 QString QSqlTableModel::tableName() const
387 Q_D(const QSqlTableModel);
392 Populates the model with data from the table that was set via setTable(), using the
393 specified filter and sort condition, and returns true if successful; otherwise
396 \note Calling select() will revert any unsubmitted changes and remove any inserted columns.
398 \sa setTable(), setFilter(), selectStatement()
400 bool QSqlTableModel::select()
403 QString query = selectStatement();
408 QSqlQuery qu(query, d->db);
411 if (!qu.isActive() || lastError().isValid()) {
412 // something went wrong - revert to non-select state
413 d->initRecordAndPrimaryIndex();
422 QVariant QSqlTableModel::data(const QModelIndex &index, int role) const
424 Q_D(const QSqlTableModel);
425 if (!index.isValid() || (role != Qt::DisplayRole && role != Qt::EditRole))
428 // Problem.. we need to use QSQM::indexInQuery to handle inserted columns
429 // but inserted rows we need to handle
430 // and indexInQuery is not virtual (grrr) so any values we pass to QSQM need
431 // to handle the insertedRows
432 QModelIndex item = indexInQuery(index);
434 switch (d->strategy) {
437 if (index.row() == d->insertIndex) {
439 if (item.column() < 0 || item.column() >= d->rec.count())
441 val = d->editBuffer.value(index.column());
442 if (val.type() == QVariant::Invalid)
443 val = QVariant(d->rec.field(item.column()).type());
446 if (d->editIndex == item.row()) {
447 QVariant var = d->editBuffer.value(item.column());
452 case OnManualSubmit: {
453 const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row());
454 const QVariant var = row.rec.value(item.column());
455 if (var.isValid() || row.op == QSqlTableModelPrivate::Insert)
460 // We need to handle row mapping here, but not column mapping
461 return QSqlQueryModel::data(index.sibling(item.row(), index.column()), role);
467 QVariant QSqlTableModel::headerData(int section, Qt::Orientation orientation, int role) const
469 Q_D(const QSqlTableModel);
470 if (orientation == Qt::Vertical && role == Qt::DisplayRole) {
471 switch (d->strategy) {
474 if (d->insertIndex == section)
475 return QLatin1String("*");
478 QSqlTableModelPrivate::Op op = d->cache.value(section).op;
479 if (op == QSqlTableModelPrivate::Insert)
480 return QLatin1String("*");
481 else if (op == QSqlTableModelPrivate::Delete)
482 return QLatin1String("!");
486 return QSqlQueryModel::headerData(section, orientation, role);
490 Returns true if the value at the index \a index is dirty, otherwise false.
491 Dirty values are values that were modified in the model
492 but not yet written into the database.
494 If \a index is invalid or points to a non-existing row, false is returned.
496 bool QSqlTableModel::isDirty(const QModelIndex &index) const
498 Q_D(const QSqlTableModel);
499 if (!index.isValid())
502 switch (d->strategy) {
506 return index.row() == d->editIndex && d->editBuffer.value(index.column()).isValid();
507 case OnManualSubmit: {
508 const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row());
509 return row.op == QSqlTableModelPrivate::Insert
510 || row.op == QSqlTableModelPrivate::Delete
511 || (row.op == QSqlTableModelPrivate::Update
512 && row.rec.value(index.column()).isValid());
519 Sets the data for the item \a index for the role \a role to \a
520 value. Depending on the edit strategy, the value might be applied
521 to the database at once or cached in the model.
523 Returns true if the value could be set or false on error, for
524 example if \a index is out of bounds.
526 \sa editStrategy(), data(), submit(), submitAll(), revertRow()
528 bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
531 if (role != Qt::EditRole)
532 return QSqlQueryModel::setData(index, value, role);
534 if (!index.isValid() || index.column() >= d->rec.count() || index.row() >= rowCount())
538 switch (d->strategy) {
539 case OnFieldChange: {
540 if (index.row() == d->insertIndex) {
541 d->editBuffer.setValue(index.column(), value);
544 d->clearEditBuffer();
545 d->editBuffer.setValue(index.column(), value);
546 isOk = updateRowInTable(index.row(), d->editBuffer);
549 emit dataChanged(index, index);
552 if (index.row() == d->insertIndex) {
553 d->editBuffer.setValue(index.column(), value);
556 if (d->editIndex != index.row()) {
557 if (d->editIndex != -1)
559 d->clearEditBuffer();
561 d->editBuffer.setValue(index.column(), value);
562 d->editIndex = index.row();
563 emit dataChanged(index, index);
565 case OnManualSubmit: {
566 QSqlTableModelPrivate::ModifiedRow &row = d->cache[index.row()];
567 if (row.op == QSqlTableModelPrivate::None) {
568 row.op = QSqlTableModelPrivate::Update;
570 row.primaryValues = d->primaryValues(indexInQuery(index).row());
572 row.rec.setValue(index.column(), value);
573 emit dataChanged(index, index);
580 This function simply calls QSqlQueryModel::setQuery(\a query).
581 You should normally not call it on a QSqlTableModel. Instead, use
582 setTable(), setSort(), setFilter(), etc., to set up the query.
584 \sa selectStatement()
586 void QSqlTableModel::setQuery(const QSqlQuery &query)
588 QSqlQueryModel::setQuery(query);
592 Updates the given \a row in the currently active database table
593 with the specified \a values. Returns true if successful; otherwise
596 This is a low-level method that operates directly on the database
597 and should not be called directly. Use setData() to update values.
598 The model will decide depending on its edit strategy when to modify
601 Note that only values that have the generated-flag set are updated.
602 The generated-flag can be set with QSqlRecord::setGenerated() and
603 tested with QSqlRecord::isGenerated().
605 \sa QSqlRecord::isGenerated(), setData()
607 bool QSqlTableModel::updateRowInTable(int row, const QSqlRecord &values)
610 QSqlRecord rec(values);
611 emit beforeUpdate(row, rec);
613 const QSqlRecord whereValues = d->strategy == OnManualSubmit ? d->cache[row].primaryValues : d->primaryValues(row);
614 bool prepStatement = d->db.driver()->hasFeature(QSqlDriver::PreparedQueries);
615 QString stmt = d->db.driver()->sqlStatement(QSqlDriver::UpdateStatement, d->tableName,
617 QString where = d->db.driver()->sqlStatement(QSqlDriver::WhereStatement, d->tableName,
618 whereValues, prepStatement);
620 if (stmt.isEmpty() || where.isEmpty() || row < 0 || row >= rowCount()) {
621 d->error = QSqlError(QLatin1String("No Fields to update"), QString(),
622 QSqlError::StatementError);
625 stmt.append(QLatin1Char(' ')).append(where);
627 return d->exec(stmt, prepStatement, rec, whereValues);
632 Inserts the values \a values into the currently active database table.
634 This is a low-level method that operates directly on the database
635 and should not be called directly. Use insertRow() and setData()
636 to insert values. The model will decide depending on its edit strategy
637 when to modify the database.
639 Returns true if the values could be inserted, otherwise false.
640 Error information can be retrieved with \l lastError().
642 \sa lastError(), insertRow(), insertRows()
644 bool QSqlTableModel::insertRowIntoTable(const QSqlRecord &values)
647 QSqlRecord rec = values;
648 emit beforeInsert(rec);
650 bool prepStatement = d->db.driver()->hasFeature(QSqlDriver::PreparedQueries);
651 QString stmt = d->db.driver()->sqlStatement(QSqlDriver::InsertStatement, d->tableName,
654 if (stmt.isEmpty()) {
655 d->error = QSqlError(QLatin1String("No Fields to update"), QString(),
656 QSqlError::StatementError);
660 return d->exec(stmt, prepStatement, rec);
664 Deletes the given \a row from the currently active database table.
666 This is a low-level method that operates directly on the database
667 and should not be called directly. Use removeRow() or removeRows()
668 to delete values. The model will decide depending on its edit strategy
669 when to modify the database.
671 Returns true if the row was deleted; otherwise returns false.
673 \sa removeRow(), removeRows()
675 bool QSqlTableModel::deleteRowFromTable(int row)
678 emit beforeDelete(row);
680 const QSqlRecord whereValues = d->strategy == OnManualSubmit ? d->cache[row].primaryValues : d->primaryValues(row);
681 bool prepStatement = d->db.driver()->hasFeature(QSqlDriver::PreparedQueries);
682 QString stmt = d->db.driver()->sqlStatement(QSqlDriver::DeleteStatement,
686 QString where = d->db.driver()->sqlStatement(QSqlDriver::WhereStatement,
691 if (stmt.isEmpty() || where.isEmpty()) {
692 d->error = QSqlError(QLatin1String("Unable to delete row"), QString(),
693 QSqlError::StatementError);
696 stmt.append(QLatin1Char(' ')).append(where);
698 return d->exec(stmt, prepStatement, whereValues);
702 Submits all pending changes and returns true on success.
703 Returns false on error, detailed error information can be
704 obtained with lastError().
706 On success the model will be repopulated. Any views
707 presenting it will lose their selections.
709 Note: In OnManualSubmit mode, already submitted changes won't
710 be cleared from the cache when submitAll() fails. This allows
711 transactions to be rolled back and resubmitted again without
714 \sa revertAll(), lastError()
716 bool QSqlTableModel::submitAll()
720 switch (d->strategy) {
722 if (d->insertIndex == -1)
726 if (d->editBuffer.isEmpty())
728 if (d->insertIndex != -1) {
729 if (!insertRowIntoTable(d->editBuffer))
731 d->bottom = d->bottom.sibling(d->bottom.row() + 1, d->bottom.column());
733 if (!updateRowInTable(d->editIndex, d->editBuffer))
736 d->clearEditBuffer();
741 for (QSqlTableModelPrivate::CacheMap::ConstIterator it = d->cache.constBegin();
742 it != d->cache.constEnd(); ++it) {
743 switch (it.value().op) {
744 case QSqlTableModelPrivate::Insert:
745 if (!insertRowIntoTable(it.value().rec))
747 d->bottom = d->bottom.sibling(d->bottom.row() + 1, d->bottom.column());
749 case QSqlTableModelPrivate::Update:
750 if (!updateRowInTable(it.key(), it.value().rec))
753 case QSqlTableModelPrivate::Delete:
754 if (!deleteRowFromTable(it.key()))
757 case QSqlTableModelPrivate::None:
758 Q_ASSERT_X(false, "QSqlTableModel::submitAll()", "Invalid cache operation");
769 This reimplemented slot is called by the item delegates when the
770 user stopped editing the current row.
772 Submits the currently edited row if the model's strategy is set
773 to OnRowChange or OnFieldChange. Does nothing for the OnManualSubmit
776 Use submitAll() to submit all pending changes for the
777 OnManualSubmit strategy.
779 Returns true on success; otherwise returns false. Use lastError()
780 to query detailed error information.
782 On success the model will be repopulated. Any views
783 presenting it will lose their selections.
785 \sa revert(), revertRow(), submitAll(), revertAll(), lastError()
787 bool QSqlTableModel::submit()
790 if (d->strategy == OnRowChange || d->strategy == OnFieldChange)
796 This reimplemented slot is called by the item delegates when the
797 user canceled editing the current row.
799 Reverts the changes if the model's strategy is set to
800 OnRowChange. Does nothing for the other edit strategies.
802 Use revertAll() to revert all pending changes for the
803 OnManualSubmit strategy or revertRow() to revert a specific row.
805 \sa submit(), submitAll(), revertRow(), revertAll()
807 void QSqlTableModel::revert()
810 if (d->strategy == OnRowChange)
815 \enum QSqlTableModel::EditStrategy
817 This enum type describes which strategy to choose when editing values in the database.
819 \value OnFieldChange All changes to the model will be applied immediately to the database.
820 \value OnRowChange Changes to a row will be applied when the user selects a different row.
821 \value OnManualSubmit All changes will be cached in the model until either submitAll()
822 or revertAll() is called.
824 Note: To prevent inserting only partly initialized rows into the database,
825 \c OnFieldChange will behave like \c OnRowChange for newly inserted rows.
827 \sa setEditStrategy()
832 Sets the strategy for editing values in the database to \a
835 This will revert any pending changes.
837 \sa editStrategy(), revertAll()
839 void QSqlTableModel::setEditStrategy(EditStrategy strategy)
843 d->strategy = strategy;
847 Returns the current edit strategy.
849 \sa setEditStrategy()
851 QSqlTableModel::EditStrategy QSqlTableModel::editStrategy() const
853 Q_D(const QSqlTableModel);
858 Reverts all pending changes.
860 \sa revert(), revertRow(), submitAll()
862 void QSqlTableModel::revertAll()
865 switch (d->strategy) {
869 if (d->editIndex != -1)
870 revertRow(d->editIndex);
871 else if (d->insertIndex != -1)
872 revertRow(d->insertIndex);
875 while (!d->cache.isEmpty())
876 revertRow(d->cache.constBegin().key());
882 Reverts all changes for the specified \a row.
884 \sa revert(), revertAll(), submit(), submitAll()
886 void QSqlTableModel::revertRow(int row)
892 switch (d->strategy) {
896 if (d->editIndex == row) {
897 d->editBuffer.clear();
898 int oldIndex = d->editIndex;
900 emit dataChanged(createIndex(oldIndex, 0), createIndex(oldIndex, columnCount()));
901 } else if (d->insertIndex == row) {
902 d->revertInsertedRow();
906 d->revertCachedRow(row);
912 Returns the primary key for the current table, or an empty
913 QSqlIndex if the table is not set or has no primary key.
915 \sa setTable(), setPrimaryKey(), QSqlDatabase::primaryIndex()
917 QSqlIndex QSqlTableModel::primaryKey() const
919 Q_D(const QSqlTableModel);
920 return d->primaryIndex;
924 Protected method that allows subclasses to set the primary key to
927 Normally, the primary index is set automatically whenever you
930 \sa primaryKey(), QSqlDatabase::primaryIndex()
932 void QSqlTableModel::setPrimaryKey(const QSqlIndex &key)
935 d->primaryIndex = key;
939 Returns a pointer to the used QSqlDatabase or 0 if no database was set.
941 QSqlDatabase QSqlTableModel::database() const
943 Q_D(const QSqlTableModel);
948 Sorts the data by \a column with the sort order \a order.
949 This will immediately select data, use setSort()
950 to set a sort order without populating the model with data.
952 \sa setSort(), select(), orderByClause()
954 void QSqlTableModel::sort(int column, Qt::SortOrder order)
956 setSort(column, order);
961 Sets the sort order for \a column to \a order. This does not
962 affect the current data, to refresh the data using the new
963 sort order, call select().
965 \sa select(), orderByClause()
967 void QSqlTableModel::setSort(int column, Qt::SortOrder order)
970 d->sortColumn = column;
971 d->sortOrder = order;
975 Returns an SQL \c{ORDER BY} clause based on the currently set
978 \sa setSort(), selectStatement()
980 QString QSqlTableModel::orderByClause() const
982 Q_D(const QSqlTableModel);
984 QSqlField f = d->rec.field(d->sortColumn);
988 QString table = d->tableName;
989 //we can safely escape the field because it would have been obtained from the database
990 //and have the correct case
991 QString field = d->db.driver()->escapeIdentifier(f.name(), QSqlDriver::FieldName);
992 s.append(QLatin1String("ORDER BY ")).append(table).append(QLatin1Char('.')).append(field);
993 s += d->sortOrder == Qt::AscendingOrder ? QLatin1String(" ASC") : QLatin1String(" DESC");
999 Returns the index of the field \a fieldName.
1001 int QSqlTableModel::fieldIndex(const QString &fieldName) const
1003 Q_D(const QSqlTableModel);
1004 return d->rec.indexOf(fieldName);
1008 Returns the SQL \c SELECT statement used internally to populate
1009 the model. The statement includes the filter and the \c{ORDER BY}
1012 \sa filter(), orderByClause()
1014 QString QSqlTableModel::selectStatement() const
1016 Q_D(const QSqlTableModel);
1018 if (d->tableName.isEmpty()) {
1019 d->error = QSqlError(QLatin1String("No table name given"), QString(),
1020 QSqlError::StatementError);
1023 if (d->rec.isEmpty()) {
1024 d->error = QSqlError(QLatin1String("Unable to find table ") + d->tableName, QString(),
1025 QSqlError::StatementError);
1029 query = d->db.driver()->sqlStatement(QSqlDriver::SelectStatement,
1033 if (query.isEmpty()) {
1034 d->error = QSqlError(QLatin1String("Unable to select fields from table ") + d->tableName,
1035 QString(), QSqlError::StatementError);
1038 if (!d->filter.isEmpty())
1039 query.append(QLatin1String(" WHERE ")).append(d->filter);
1040 QString orderBy(orderByClause());
1041 if (!orderBy.isEmpty())
1042 query.append(QLatin1Char(' ')).append(orderBy);
1048 Removes \a count columns from the \a parent model, starting at
1051 Returns if the columns were successfully removed; otherwise
1056 bool QSqlTableModel::removeColumns(int column, int count, const QModelIndex &parent)
1058 Q_D(QSqlTableModel);
1059 if (parent.isValid() || column < 0 || column + count > d->rec.count())
1061 for (int i = 0; i < count; ++i)
1062 d->rec.remove(column);
1063 if (d->query.isActive())
1069 Removes \a count rows starting at \a row. Since this model
1070 does not support hierarchical structures, \a parent must be
1071 an invalid model index.
1073 Emits the beforeDelete() signal before a row is deleted. When
1074 the edit strategy is OnManualSubmit signal emission is delayed
1075 until submitAll() is called.
1077 Returns true if all rows could be removed; otherwise returns
1078 false. Detailed error information can be retrieved using
1081 \sa removeColumns(), insertRows()
1083 bool QSqlTableModel::removeRows(int row, int count, const QModelIndex &parent)
1085 Q_D(QSqlTableModel);
1086 if (parent.isValid() || row < 0 || count <= 0)
1090 switch (d->strategy) {
1093 for (i = 0; i < count; ++i) {
1094 if (row + i == d->insertIndex)
1095 d->revertInsertedRow();
1096 else if (!deleteRowFromTable(row + i))
1101 case OnManualSubmit:
1102 for (i = 0; i < count; ++i) {
1104 if (idx >= rowCount())
1106 if (d->cache.value(idx).op == QSqlTableModelPrivate::Insert)
1109 d->cache[idx].op = QSqlTableModelPrivate::Delete;
1110 d->cache[idx].primaryValues = d->primaryValues(indexInQuery(createIndex(idx, 0)).row());
1111 emit headerDataChanged(Qt::Vertical, idx, idx);
1120 Inserts \a count empty rows at position \a row. Note that \a
1121 parent must be invalid, since this model does not support
1122 parent-child relations.
1124 Only one row at a time can be inserted when using the
1125 OnFieldChange or OnRowChange update strategies.
1127 The primeInsert() signal will be emitted for each new row.
1128 Connect to it if you want to initialize the new row with default
1131 Returns false if the parameters are out of bounds; otherwise
1134 \sa primeInsert(), insertRecord()
1136 bool QSqlTableModel::insertRows(int row, int count, const QModelIndex &parent)
1138 Q_D(QSqlTableModel);
1139 if (row < 0 || count <= 0 || row > rowCount() || parent.isValid())
1142 switch (d->strategy) {
1147 beginInsertRows(parent, row, row);
1148 d->insertIndex = row;
1149 // ### apply dangling changes...
1150 d->clearEditBuffer();
1151 emit primeInsert(row, d->editBuffer);
1153 case OnManualSubmit:
1154 beginInsertRows(parent, row, row + count - 1);
1155 if (!d->cache.isEmpty()) {
1156 QMap<int, QSqlTableModelPrivate::ModifiedRow>::Iterator it = d->cache.end();
1157 while (it != d->cache.begin() && (--it).key() >= row) {
1158 int oldKey = it.key();
1159 const QSqlTableModelPrivate::ModifiedRow oldValue = it.value();
1161 it = d->cache.insert(oldKey + count, oldValue);
1165 for (int i = 0; i < count; ++i) {
1166 d->cache[row + i] = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Insert,
1168 emit primeInsert(row + i, d->cache[row + i].rec);
1177 Inserts the \a record after \a row. If \a row is negative, the
1178 record will be appended to the end. Calls insertRows() and
1179 setRecord() internally.
1181 Returns true if the row could be inserted, otherwise false.
1183 \sa insertRows(), removeRows()
1185 bool QSqlTableModel::insertRecord(int row, const QSqlRecord &record)
1187 Q_D(QSqlTableModel);
1190 if (!insertRow(row, QModelIndex()))
1192 if (!setRecord(row, record))
1194 if (d->strategy == OnFieldChange || d->strategy == OnRowChange)
1201 int QSqlTableModel::rowCount(const QModelIndex &parent) const
1203 Q_D(const QSqlTableModel);
1205 if (parent.isValid())
1208 int rc = QSqlQueryModel::rowCount();
1209 if (d->strategy == OnManualSubmit) {
1210 for (QSqlTableModelPrivate::CacheMap::ConstIterator it = d->cache.constBegin();
1211 it != d->cache.constEnd(); ++it) {
1212 if (it.value().op == QSqlTableModelPrivate::Insert)
1215 } else if (d->insertIndex >= 0) {
1222 Returns the index of the value in the database result set for the
1223 given \a item in the model.
1225 The return value is identical to \a item if no columns or rows
1226 have been inserted, removed, or moved around.
1228 Returns an invalid model index if \a item is out of bounds or if
1229 \a item does not point to a value in the result set.
1231 \sa QSqlQueryModel::indexInQuery()
1233 QModelIndex QSqlTableModel::indexInQuery(const QModelIndex &item) const
1235 Q_D(const QSqlTableModel);
1236 const QModelIndex it = QSqlQueryModel::indexInQuery(item); // this adjusts columns only
1237 if (d->strategy == OnManualSubmit) {
1239 QSqlTableModelPrivate::CacheMap::ConstIterator i = d->cache.constBegin();
1240 while (i != d->cache.constEnd() && i.key() <= it.row()) {
1241 if (i.value().op == QSqlTableModelPrivate::Insert)
1245 return createIndex(it.row() - rowOffset, it.column(), it.internalPointer());
1247 if (d->insertIndex >= 0 && it.row() >= d->insertIndex)
1248 return createIndex(it.row() - 1, it.column(), it.internalPointer());
1254 Returns the currently set filter.
1256 \sa setFilter(), select()
1258 QString QSqlTableModel::filter() const
1260 Q_D(const QSqlTableModel);
1265 Sets the current filter to \a filter.
1267 The filter is a SQL \c WHERE clause without the keyword \c WHERE
1268 (for example, \c{name='Josephine')}.
1270 If the model is already populated with data from a database,
1271 the model re-selects it with the new filter. Otherwise, the filter
1272 will be applied the next time select() is called.
1274 \sa filter(), select(), selectStatement(), orderByClause()
1276 void QSqlTableModel::setFilter(const QString &filter)
1278 Q_D(QSqlTableModel);
1280 if (d->query.isActive())
1286 void QSqlTableModel::clear()
1288 Q_D(QSqlTableModel);
1290 QSqlQueryModel::clear();
1295 Qt::ItemFlags QSqlTableModel::flags(const QModelIndex &index) const
1297 Q_D(const QSqlTableModel);
1298 if (index.internalPointer() || index.column() < 0 || index.column() >= d->rec.count()
1301 if (d->rec.field(index.column()).isReadOnly())
1302 return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
1303 return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
1307 Sets the values at the specified \a row to the values of \a
1308 record. Returns true if all the values could be set; otherwise
1313 bool QSqlTableModel::setRecord(int row, const QSqlRecord &record)
1315 Q_D(QSqlTableModel);
1316 Q_ASSERT_X(row >= 0, "QSqlTableModel::setRecord()", "Cannot set a record to a row less than 0");
1317 if (row >= rowCount())
1321 switch (d->strategy) {
1324 return d->setRecord(row, record);
1325 case OnManualSubmit: {
1326 QSqlTableModelPrivate::ModifiedRow &mrow = d->cache[row];
1327 if (mrow.op == QSqlTableModelPrivate::None) {
1328 mrow.op = QSqlTableModelPrivate::Update;
1330 mrow.primaryValues = d->primaryValues(indexInQuery(createIndex(row, 0)).row());
1333 for (int i = 0; i < record.count(); ++i) {
1334 fieldName = record.fieldName(i);
1335 if (d->db.driver()->isIdentifierEscaped(fieldName, QSqlDriver::FieldName))
1336 fieldName = d->db.driver()->stripDelimiters(fieldName, QSqlDriver::FieldName);
1337 int idx = mrow.rec.indexOf(fieldName);
1341 mrow.rec.setValue(idx, record.value(i));
1345 emit dataChanged(createIndex(row, 0), createIndex(row, columnCount() - 1));