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 QModelIndex item = indexInQuery(index);
430 switch (d->strategy) {
433 if (index.row() == d->insertIndex) {
435 if (item.column() < 0 || item.column() >= d->rec.count())
437 val = d->editBuffer.value(index.column());
438 if (val.type() == QVariant::Invalid)
439 val = QVariant(d->rec.field(item.column()).type());
442 if (d->editIndex == item.row()) {
443 QVariant var = d->editBuffer.value(item.column());
448 case OnManualSubmit: {
449 const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row());
450 const QVariant var = row.rec.value(item.column());
451 if (var.isValid() || row.op == QSqlTableModelPrivate::Insert)
455 return QSqlQueryModel::data(item, role);
461 QVariant QSqlTableModel::headerData(int section, Qt::Orientation orientation, int role) const
463 Q_D(const QSqlTableModel);
464 if (orientation == Qt::Vertical && role == Qt::DisplayRole) {
465 switch (d->strategy) {
468 if (d->insertIndex == section)
469 return QLatin1String("*");
472 QSqlTableModelPrivate::Op op = d->cache.value(section).op;
473 if (op == QSqlTableModelPrivate::Insert)
474 return QLatin1String("*");
475 else if (op == QSqlTableModelPrivate::Delete)
476 return QLatin1String("!");
480 return QSqlQueryModel::headerData(section, orientation, role);
484 Returns true if the value at the index \a index is dirty, otherwise false.
485 Dirty values are values that were modified in the model
486 but not yet written into the database.
488 If \a index is invalid or points to a non-existing row, false is returned.
490 bool QSqlTableModel::isDirty(const QModelIndex &index) const
492 Q_D(const QSqlTableModel);
493 if (!index.isValid())
496 switch (d->strategy) {
500 return index.row() == d->editIndex && d->editBuffer.value(index.column()).isValid();
501 case OnManualSubmit: {
502 const QSqlTableModelPrivate::ModifiedRow row = d->cache.value(index.row());
503 return row.op == QSqlTableModelPrivate::Insert
504 || row.op == QSqlTableModelPrivate::Delete
505 || (row.op == QSqlTableModelPrivate::Update
506 && row.rec.value(index.column()).isValid());
513 Sets the data for the item \a index for the role \a role to \a
514 value. Depending on the edit strategy, the value might be applied
515 to the database at once or cached in the model.
517 Returns true if the value could be set or false on error, for
518 example if \a index is out of bounds.
520 \sa editStrategy(), data(), submit(), submitAll(), revertRow()
522 bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
525 if (role != Qt::EditRole)
526 return QSqlQueryModel::setData(index, value, role);
528 if (!index.isValid() || index.column() >= d->rec.count() || index.row() >= rowCount())
532 switch (d->strategy) {
533 case OnFieldChange: {
534 if (index.row() == d->insertIndex) {
535 d->editBuffer.setValue(index.column(), value);
538 d->clearEditBuffer();
539 d->editBuffer.setValue(index.column(), value);
540 isOk = updateRowInTable(index.row(), d->editBuffer);
543 emit dataChanged(index, index);
546 if (index.row() == d->insertIndex) {
547 d->editBuffer.setValue(index.column(), value);
550 if (d->editIndex != index.row()) {
551 if (d->editIndex != -1)
553 d->clearEditBuffer();
555 d->editBuffer.setValue(index.column(), value);
556 d->editIndex = index.row();
557 emit dataChanged(index, index);
559 case OnManualSubmit: {
560 QSqlTableModelPrivate::ModifiedRow &row = d->cache[index.row()];
561 if (row.op == QSqlTableModelPrivate::None) {
562 row.op = QSqlTableModelPrivate::Update;
564 row.primaryValues = d->primaryValues(indexInQuery(index).row());
566 row.rec.setValue(index.column(), value);
567 emit dataChanged(index, index);
574 This function simply calls QSqlQueryModel::setQuery(\a query).
575 You should normally not call it on a QSqlTableModel. Instead, use
576 setTable(), setSort(), setFilter(), etc., to set up the query.
578 \sa selectStatement()
580 void QSqlTableModel::setQuery(const QSqlQuery &query)
582 QSqlQueryModel::setQuery(query);
586 Updates the given \a row in the currently active database table
587 with the specified \a values. Returns true if successful; otherwise
590 This is a low-level method that operates directly on the database
591 and should not be called directly. Use setData() to update values.
592 The model will decide depending on its edit strategy when to modify
595 Note that only values that have the generated-flag set are updated.
596 The generated-flag can be set with QSqlRecord::setGenerated() and
597 tested with QSqlRecord::isGenerated().
599 \sa QSqlRecord::isGenerated(), setData()
601 bool QSqlTableModel::updateRowInTable(int row, const QSqlRecord &values)
604 QSqlRecord rec(values);
605 emit beforeUpdate(row, rec);
607 const QSqlRecord whereValues = d->strategy == OnManualSubmit ? d->cache[row].primaryValues : d->primaryValues(row);
608 bool prepStatement = d->db.driver()->hasFeature(QSqlDriver::PreparedQueries);
609 QString stmt = d->db.driver()->sqlStatement(QSqlDriver::UpdateStatement, d->tableName,
611 QString where = d->db.driver()->sqlStatement(QSqlDriver::WhereStatement, d->tableName,
612 whereValues, prepStatement);
614 if (stmt.isEmpty() || where.isEmpty() || row < 0 || row >= rowCount()) {
615 d->error = QSqlError(QLatin1String("No Fields to update"), QString(),
616 QSqlError::StatementError);
619 stmt.append(QLatin1Char(' ')).append(where);
621 return d->exec(stmt, prepStatement, rec, whereValues);
626 Inserts the values \a values into the currently active database table.
628 This is a low-level method that operates directly on the database
629 and should not be called directly. Use insertRow() and setData()
630 to insert values. The model will decide depending on its edit strategy
631 when to modify the database.
633 Returns true if the values could be inserted, otherwise false.
634 Error information can be retrieved with \l lastError().
636 \sa lastError(), insertRow(), insertRows()
638 bool QSqlTableModel::insertRowIntoTable(const QSqlRecord &values)
641 QSqlRecord rec = values;
642 emit beforeInsert(rec);
644 bool prepStatement = d->db.driver()->hasFeature(QSqlDriver::PreparedQueries);
645 QString stmt = d->db.driver()->sqlStatement(QSqlDriver::InsertStatement, d->tableName,
648 if (stmt.isEmpty()) {
649 d->error = QSqlError(QLatin1String("No Fields to update"), QString(),
650 QSqlError::StatementError);
654 return d->exec(stmt, prepStatement, rec);
658 Deletes the given \a row from the currently active database table.
660 This is a low-level method that operates directly on the database
661 and should not be called directly. Use removeRow() or removeRows()
662 to delete values. The model will decide depending on its edit strategy
663 when to modify the database.
665 Returns true if the row was deleted; otherwise returns false.
667 \sa removeRow(), removeRows()
669 bool QSqlTableModel::deleteRowFromTable(int row)
672 emit beforeDelete(row);
674 const QSqlRecord whereValues = d->strategy == OnManualSubmit ? d->cache[row].primaryValues : d->primaryValues(row);
675 bool prepStatement = d->db.driver()->hasFeature(QSqlDriver::PreparedQueries);
676 QString stmt = d->db.driver()->sqlStatement(QSqlDriver::DeleteStatement,
680 QString where = d->db.driver()->sqlStatement(QSqlDriver::WhereStatement,
685 if (stmt.isEmpty() || where.isEmpty()) {
686 d->error = QSqlError(QLatin1String("Unable to delete row"), QString(),
687 QSqlError::StatementError);
690 stmt.append(QLatin1Char(' ')).append(where);
692 return d->exec(stmt, prepStatement, whereValues);
696 Submits all pending changes and returns true on success.
697 Returns false on error, detailed error information can be
698 obtained with lastError().
700 On success the model will be repopulated. Any views
701 presenting it will lose their selections.
703 Note: In OnManualSubmit mode, already submitted changes won't
704 be cleared from the cache when submitAll() fails. This allows
705 transactions to be rolled back and resubmitted again without
708 \sa revertAll(), lastError()
710 bool QSqlTableModel::submitAll()
714 switch (d->strategy) {
716 if (d->insertIndex == -1)
720 if (d->editBuffer.isEmpty())
722 if (d->insertIndex != -1) {
723 if (!insertRowIntoTable(d->editBuffer))
725 d->bottom = d->bottom.sibling(d->bottom.row() + 1, d->bottom.column());
727 if (!updateRowInTable(d->editIndex, d->editBuffer))
730 d->clearEditBuffer();
735 for (QSqlTableModelPrivate::CacheMap::ConstIterator it = d->cache.constBegin();
736 it != d->cache.constEnd(); ++it) {
737 switch (it.value().op) {
738 case QSqlTableModelPrivate::Insert:
739 if (!insertRowIntoTable(it.value().rec))
741 d->bottom = d->bottom.sibling(d->bottom.row() + 1, d->bottom.column());
743 case QSqlTableModelPrivate::Update:
744 if (!updateRowInTable(it.key(), it.value().rec))
747 case QSqlTableModelPrivate::Delete:
748 if (!deleteRowFromTable(it.key()))
751 case QSqlTableModelPrivate::None:
752 Q_ASSERT_X(false, "QSqlTableModel::submitAll()", "Invalid cache operation");
763 This reimplemented slot is called by the item delegates when the
764 user stopped editing the current row.
766 Submits the currently edited row if the model's strategy is set
767 to OnRowChange or OnFieldChange. Does nothing for the OnManualSubmit
770 Use submitAll() to submit all pending changes for the
771 OnManualSubmit strategy.
773 Returns true on success; otherwise returns false. Use lastError()
774 to query detailed error information.
776 On success the model will be repopulated. Any views
777 presenting it will lose their selections.
779 \sa revert(), revertRow(), submitAll(), revertAll(), lastError()
781 bool QSqlTableModel::submit()
784 if (d->strategy == OnRowChange || d->strategy == OnFieldChange)
790 This reimplemented slot is called by the item delegates when the
791 user canceled editing the current row.
793 Reverts the changes if the model's strategy is set to
794 OnRowChange. Does nothing for the other edit strategies.
796 Use revertAll() to revert all pending changes for the
797 OnManualSubmit strategy or revertRow() to revert a specific row.
799 \sa submit(), submitAll(), revertRow(), revertAll()
801 void QSqlTableModel::revert()
804 if (d->strategy == OnRowChange)
809 \enum QSqlTableModel::EditStrategy
811 This enum type describes which strategy to choose when editing values in the database.
813 \value OnFieldChange All changes to the model will be applied immediately to the database.
814 \value OnRowChange Changes to a row will be applied when the user selects a different row.
815 \value OnManualSubmit All changes will be cached in the model until either submitAll()
816 or revertAll() is called.
818 Note: To prevent inserting only partly initialized rows into the database,
819 \c OnFieldChange will behave like \c OnRowChange for newly inserted rows.
821 \sa setEditStrategy()
826 Sets the strategy for editing values in the database to \a
829 This will revert any pending changes.
831 \sa editStrategy(), revertAll()
833 void QSqlTableModel::setEditStrategy(EditStrategy strategy)
837 d->strategy = strategy;
841 Returns the current edit strategy.
843 \sa setEditStrategy()
845 QSqlTableModel::EditStrategy QSqlTableModel::editStrategy() const
847 Q_D(const QSqlTableModel);
852 Reverts all pending changes.
854 \sa revert(), revertRow(), submitAll()
856 void QSqlTableModel::revertAll()
859 switch (d->strategy) {
863 if (d->editIndex != -1)
864 revertRow(d->editIndex);
865 else if (d->insertIndex != -1)
866 revertRow(d->insertIndex);
869 while (!d->cache.isEmpty())
870 revertRow(d->cache.constBegin().key());
876 Reverts all changes for the specified \a row.
878 \sa revert(), revertAll(), submit(), submitAll()
880 void QSqlTableModel::revertRow(int row)
886 switch (d->strategy) {
890 if (d->editIndex == row) {
891 d->editBuffer.clear();
892 int oldIndex = d->editIndex;
894 emit dataChanged(createIndex(oldIndex, 0), createIndex(oldIndex, columnCount()));
895 } else if (d->insertIndex == row) {
896 d->revertInsertedRow();
900 d->revertCachedRow(row);
906 Returns the primary key for the current table, or an empty
907 QSqlIndex if the table is not set or has no primary key.
909 \sa setTable(), setPrimaryKey(), QSqlDatabase::primaryIndex()
911 QSqlIndex QSqlTableModel::primaryKey() const
913 Q_D(const QSqlTableModel);
914 return d->primaryIndex;
918 Protected method that allows subclasses to set the primary key to
921 Normally, the primary index is set automatically whenever you
924 \sa primaryKey(), QSqlDatabase::primaryIndex()
926 void QSqlTableModel::setPrimaryKey(const QSqlIndex &key)
929 d->primaryIndex = key;
933 Returns a pointer to the used QSqlDatabase or 0 if no database was set.
935 QSqlDatabase QSqlTableModel::database() const
937 Q_D(const QSqlTableModel);
942 Sorts the data by \a column with the sort order \a order.
943 This will immediately select data, use setSort()
944 to set a sort order without populating the model with data.
946 \sa setSort(), select(), orderByClause()
948 void QSqlTableModel::sort(int column, Qt::SortOrder order)
950 setSort(column, order);
955 Sets the sort order for \a column to \a order. This does not
956 affect the current data, to refresh the data using the new
957 sort order, call select().
959 \sa select(), orderByClause()
961 void QSqlTableModel::setSort(int column, Qt::SortOrder order)
964 d->sortColumn = column;
965 d->sortOrder = order;
969 Returns an SQL \c{ORDER BY} clause based on the currently set
972 \sa setSort(), selectStatement()
974 QString QSqlTableModel::orderByClause() const
976 Q_D(const QSqlTableModel);
978 QSqlField f = d->rec.field(d->sortColumn);
982 QString table = d->tableName;
983 //we can safely escape the field because it would have been obtained from the database
984 //and have the correct case
985 QString field = d->db.driver()->escapeIdentifier(f.name(), QSqlDriver::FieldName);
986 s.append(QLatin1String("ORDER BY ")).append(table).append(QLatin1Char('.')).append(field);
987 s += d->sortOrder == Qt::AscendingOrder ? QLatin1String(" ASC") : QLatin1String(" DESC");
993 Returns the index of the field \a fieldName.
995 int QSqlTableModel::fieldIndex(const QString &fieldName) const
997 Q_D(const QSqlTableModel);
998 return d->rec.indexOf(fieldName);
1002 Returns the SQL \c SELECT statement used internally to populate
1003 the model. The statement includes the filter and the \c{ORDER BY}
1006 \sa filter(), orderByClause()
1008 QString QSqlTableModel::selectStatement() const
1010 Q_D(const QSqlTableModel);
1012 if (d->tableName.isEmpty()) {
1013 d->error = QSqlError(QLatin1String("No table name given"), QString(),
1014 QSqlError::StatementError);
1017 if (d->rec.isEmpty()) {
1018 d->error = QSqlError(QLatin1String("Unable to find table ") + d->tableName, QString(),
1019 QSqlError::StatementError);
1023 query = d->db.driver()->sqlStatement(QSqlDriver::SelectStatement,
1027 if (query.isEmpty()) {
1028 d->error = QSqlError(QLatin1String("Unable to select fields from table ") + d->tableName,
1029 QString(), QSqlError::StatementError);
1032 if (!d->filter.isEmpty())
1033 query.append(QLatin1String(" WHERE ")).append(d->filter);
1034 QString orderBy(orderByClause());
1035 if (!orderBy.isEmpty())
1036 query.append(QLatin1Char(' ')).append(orderBy);
1042 Removes \a count columns from the \a parent model, starting at
1045 Returns if the columns were successfully removed; otherwise
1050 bool QSqlTableModel::removeColumns(int column, int count, const QModelIndex &parent)
1052 Q_D(QSqlTableModel);
1053 if (parent.isValid() || column < 0 || column + count > d->rec.count())
1055 for (int i = 0; i < count; ++i)
1056 d->rec.remove(column);
1057 if (d->query.isActive())
1063 Removes \a count rows starting at \a row. Since this model
1064 does not support hierarchical structures, \a parent must be
1065 an invalid model index.
1067 Emits the beforeDelete() signal before a row is deleted. When
1068 the edit strategy is OnManualSubmit signal emission is delayed
1069 until submitAll() is called.
1071 Returns true if all rows could be removed; otherwise returns
1072 false. Detailed error information can be retrieved using
1075 \sa removeColumns(), insertRows()
1077 bool QSqlTableModel::removeRows(int row, int count, const QModelIndex &parent)
1079 Q_D(QSqlTableModel);
1080 if (parent.isValid() || row < 0 || count <= 0)
1084 switch (d->strategy) {
1087 for (i = 0; i < count; ++i) {
1088 if (row + i == d->insertIndex)
1089 d->revertInsertedRow();
1090 else if (!deleteRowFromTable(row + i))
1095 case OnManualSubmit:
1096 for (i = 0; i < count; ++i) {
1098 if (idx >= rowCount())
1100 if (d->cache.value(idx).op == QSqlTableModelPrivate::Insert) {
1102 // Reverting a row means all the other cache entries have been adjusted downwards
1103 // so fake this by adjusting row
1106 d->cache[idx].op = QSqlTableModelPrivate::Delete;
1107 d->cache[idx].primaryValues = d->primaryValues(indexInQuery(createIndex(idx, 0)).row());
1108 emit headerDataChanged(Qt::Vertical, idx, idx);
1117 Inserts \a count empty rows at position \a row. Note that \a
1118 parent must be invalid, since this model does not support
1119 parent-child relations.
1121 Only one row at a time can be inserted when using the
1122 OnFieldChange or OnRowChange update strategies.
1124 The primeInsert() signal will be emitted for each new row.
1125 Connect to it if you want to initialize the new row with default
1128 Returns false if the parameters are out of bounds; otherwise
1131 \sa primeInsert(), insertRecord()
1133 bool QSqlTableModel::insertRows(int row, int count, const QModelIndex &parent)
1135 Q_D(QSqlTableModel);
1136 if (row < 0 || count <= 0 || row > rowCount() || parent.isValid())
1139 switch (d->strategy) {
1144 beginInsertRows(parent, row, row);
1145 d->insertIndex = row;
1146 // ### apply dangling changes...
1147 d->clearEditBuffer();
1148 emit primeInsert(row, d->editBuffer);
1150 case OnManualSubmit:
1151 beginInsertRows(parent, row, row + count - 1);
1152 if (!d->cache.isEmpty()) {
1153 QMap<int, QSqlTableModelPrivate::ModifiedRow>::Iterator it = d->cache.end();
1154 while (it != d->cache.begin() && (--it).key() >= row) {
1155 int oldKey = it.key();
1156 const QSqlTableModelPrivate::ModifiedRow oldValue = it.value();
1158 it = d->cache.insert(oldKey + count, oldValue);
1162 for (int i = 0; i < count; ++i) {
1163 d->cache[row + i] = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Insert,
1165 emit primeInsert(row + i, d->cache[row + i].rec);
1174 Inserts the \a record after \a row. If \a row is negative, the
1175 record will be appended to the end. Calls insertRows() and
1176 setRecord() internally.
1178 Returns true if the row could be inserted, otherwise false.
1180 \sa insertRows(), removeRows()
1182 bool QSqlTableModel::insertRecord(int row, const QSqlRecord &record)
1184 Q_D(QSqlTableModel);
1187 if (!insertRow(row, QModelIndex()))
1189 if (!setRecord(row, record))
1191 if (d->strategy == OnFieldChange || d->strategy == OnRowChange)
1198 int QSqlTableModel::rowCount(const QModelIndex &parent) const
1200 Q_D(const QSqlTableModel);
1202 if (parent.isValid())
1205 int rc = QSqlQueryModel::rowCount();
1206 if (d->strategy == OnManualSubmit) {
1207 for (QSqlTableModelPrivate::CacheMap::ConstIterator it = d->cache.constBegin();
1208 it != d->cache.constEnd(); ++it) {
1209 if (it.value().op == QSqlTableModelPrivate::Insert)
1212 } else if (d->insertIndex >= 0) {
1219 Returns the index of the value in the database result set for the
1220 given \a item in the model.
1222 The return value is identical to \a item if no columns or rows
1223 have been inserted, removed, or moved around.
1225 Returns an invalid model index if \a item is out of bounds or if
1226 \a item does not point to a value in the result set.
1228 \sa QSqlQueryModel::indexInQuery()
1230 QModelIndex QSqlTableModel::indexInQuery(const QModelIndex &item) const
1232 Q_D(const QSqlTableModel);
1233 const QModelIndex it = QSqlQueryModel::indexInQuery(item);
1234 if (d->strategy == OnManualSubmit) {
1236 QSqlTableModelPrivate::CacheMap::ConstIterator i = d->cache.constBegin();
1237 while (i != d->cache.constEnd() && i.key() <= it.row()) {
1238 if (i.value().op == QSqlTableModelPrivate::Insert)
1242 return createIndex(it.row() - rowOffset, it.column(), it.internalPointer());
1244 if (d->insertIndex >= 0 && it.row() >= d->insertIndex)
1245 return createIndex(it.row() - 1, it.column(), it.internalPointer());
1251 Returns the currently set filter.
1253 \sa setFilter(), select()
1255 QString QSqlTableModel::filter() const
1257 Q_D(const QSqlTableModel);
1262 Sets the current filter to \a filter.
1264 The filter is a SQL \c WHERE clause without the keyword \c WHERE
1265 (for example, \c{name='Josephine')}.
1267 If the model is already populated with data from a database,
1268 the model re-selects it with the new filter. Otherwise, the filter
1269 will be applied the next time select() is called.
1271 \sa filter(), select(), selectStatement(), orderByClause()
1273 void QSqlTableModel::setFilter(const QString &filter)
1275 Q_D(QSqlTableModel);
1277 if (d->query.isActive())
1283 void QSqlTableModel::clear()
1285 Q_D(QSqlTableModel);
1287 QSqlQueryModel::clear();
1292 Qt::ItemFlags QSqlTableModel::flags(const QModelIndex &index) const
1294 Q_D(const QSqlTableModel);
1295 if (index.internalPointer() || index.column() < 0 || index.column() >= d->rec.count()
1298 if (d->rec.field(index.column()).isReadOnly())
1299 return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
1300 return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
1304 Sets the values at the specified \a row to the values of \a
1305 record. Returns true if all the values could be set; otherwise
1310 bool QSqlTableModel::setRecord(int row, const QSqlRecord &record)
1312 Q_D(QSqlTableModel);
1313 Q_ASSERT_X(row >= 0, "QSqlTableModel::setRecord()", "Cannot set a record to a row less than 0");
1314 if (row >= rowCount())
1318 switch (d->strategy) {
1321 return d->setRecord(row, record);
1322 case OnManualSubmit: {
1323 QSqlTableModelPrivate::ModifiedRow &mrow = d->cache[row];
1324 if (mrow.op == QSqlTableModelPrivate::None) {
1325 mrow.op = QSqlTableModelPrivate::Update;
1327 mrow.primaryValues = d->primaryValues(indexInQuery(createIndex(row, 0)).row());
1330 for (int i = 0; i < record.count(); ++i) {
1331 fieldName = record.fieldName(i);
1332 if (d->db.driver()->isIdentifierEscaped(fieldName, QSqlDriver::FieldName))
1333 fieldName = d->db.driver()->stripDelimiters(fieldName, QSqlDriver::FieldName);
1334 int idx = mrow.rec.indexOf(fieldName);
1338 mrow.rec.setValue(idx, record.value(i));
1342 emit dataChanged(createIndex(row, 0), createIndex(row, columnCount() - 1));