Update some documentation about what happens with select()/setQuery().
[qt:qt.git] / src / sql / models / qsqltablemodel.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 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 ** 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
14 ** this package.
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 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qsqltablemodel.h"
43
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"
51
52 #include "qsqltablemodel_p.h"
53
54 #include <qdebug.h>
55
56 QT_BEGIN_NAMESPACE
57
58 /*! \internal
59     Populates our record with values.
60 */
61 QSqlRecord QSqlTableModelPrivate::record(const QVector<QVariant> &values) const
62 {
63     QSqlRecord r = rec;
64     for (int i = 0; i < r.count() && i < values.count(); ++i)
65         r.setValue(i, values.at(i));
66     return r;
67 }
68
69 /*! \internal
70     Set a record for OnFieldChange and OnRowChange.
71 */
72 bool QSqlTableModelPrivate::setRecord(int row, const QSqlRecord &record)
73 {
74     Q_Q(QSqlTableModel);
75     bool isOk = true;
76
77     QSqlTableModel::EditStrategy oldStrategy = strategy;
78
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));
84         if (idx == -1)
85             continue;
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);
91     }
92     if (isOk && oldStrategy == QSqlTableModel::OnFieldChange)
93         q->submitAll();
94     strategy = oldStrategy;
95
96     return isOk;
97 }
98
99 int QSqlTableModelPrivate::nameToIndex(const QString &name) const
100 {
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);
105 }
106
107 void QSqlTableModelPrivate::initRecordAndPrimaryIndex()
108 {
109     rec = db.record(tableName);
110     primaryIndex = db.primaryIndex(tableName);
111 }
112
113 void QSqlTableModelPrivate::clear()
114 {
115     editIndex = -1;
116     sortColumn = -1;
117     sortOrder = Qt::AscendingOrder;
118     tableName.clear();
119     editQuery.clear();
120     editBuffer.clear();
121     cache.clear();
122     primaryIndex.clear();
123     rec.clear();
124     filter.clear();
125 }
126
127 void QSqlTableModelPrivate::revertInsertedRow()
128 {
129     Q_Q(QSqlTableModel);
130     if (insertIndex == -1)
131         return;
132
133     q->beginRemoveRows(QModelIndex(), insertIndex, insertIndex);
134     insertIndex = -1;
135     q->endRemoveRows();
136 }
137
138 void QSqlTableModelPrivate::clearEditBuffer()
139 {
140     editBuffer = rec;
141 }
142
143 void QSqlTableModelPrivate::clearCache()
144 {
145     cache.clear();
146 }
147
148 void QSqlTableModelPrivate::revertCachedRow(int row)
149 {
150     Q_Q(QSqlTableModel);
151     ModifiedRow r = cache.value(row);
152     switch (r.op) {
153     case QSqlTableModelPrivate::None:
154         Q_ASSERT_X(false, "QSqlTableModelPrivate::revertCachedRow()", "Invalid entry in cache map");
155         return;
156     case QSqlTableModelPrivate::Update:
157     case QSqlTableModelPrivate::Delete:
158         cache.remove(row);
159         emit q->dataChanged(q->createIndex(row, 0),
160                             q->createIndex(row, q->columnCount() - 1));
161         break;
162     case QSqlTableModelPrivate::Insert: {
163             QMap<int, QSqlTableModelPrivate::ModifiedRow>::Iterator it = cache.find(row);
164             if (it == cache.end())
165                 return;
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();
171                 cache.erase(it);
172                 it = cache.insert(oldKey - 1, oldValue);
173                 ++it;
174             }
175             q->endRemoveRows();
176         break; }
177     }
178 }
179
180 bool QSqlTableModelPrivate::exec(const QString &stmt, bool prepStatement,
181                                  const QSqlRecord &rec, const QSqlRecord &whereValues)
182 {
183     if (stmt.isEmpty())
184         return false;
185
186     // lazy initialization of editQuery
187     if (editQuery.driver() != db.driver())
188         editQuery = QSqlQuery(db);
189
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();
194
195     if (prepStatement) {
196         if (editQuery.lastQuery() != stmt) {
197             if (!editQuery.prepare(stmt)) {
198                 error = editQuery.lastError();
199                 return false;
200             }
201         }
202         int i;
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));
206         }
207         for (i = 0; i < whereValues.count(); ++i) {
208             if (whereValues.isGenerated(i) && !whereValues.isNull(i))
209                 editQuery.addBindValue(whereValues.value(i));
210         }
211
212         if (!editQuery.exec()) {
213             error = editQuery.lastError();
214             return false;
215         }
216     } else {
217         if (!editQuery.exec(stmt)) {
218             error = editQuery.lastError();
219             return false;
220         }
221     }
222     return true;
223 }
224
225 QSqlRecord QSqlTableModelPrivate::primaryValues(int row)
226 {
227     QSqlRecord record;
228     if (!query.seek(row)) {
229         error = query.lastError();
230         return record;
231     }
232     if (primaryIndex.isEmpty()) {
233         record = rec;
234         for (int i = 0; i < record.count(); ++i)
235             record.setValue(i, query.value(i));
236     } else {
237         record = primaryIndex;
238         for (int i = 0; i < record.count(); ++i)
239             record.setValue(i, query.value(rec.indexOf(record.fieldName(i))));
240     }
241     return record;
242 }
243
244 /*!
245     \class QSqlTableModel
246     \brief The QSqlTableModel class provides an editable data model
247     for a single database table.
248
249     \ingroup database
250     \inmodule QtSql
251
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:
256
257     \snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 24
258
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.
264
265     QSqlTableModel can also be used to access a database
266     programmatically, without binding it to a view:
267
268     \snippet doc/src/snippets/sqldatabase/sqldatabase.cpp 21
269
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}.
272
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.
276
277     The \l{sql/tablemodel} example illustrates how to use
278     QSqlTableModel as the data source for a QTableView.
279
280     QSqlTableModel provides no direct support for foreign keys. Use
281     the QSqlRelationalTableModel and QSqlRelationalDelegate if you
282     want to resolve foreign keys.
283
284     \sa QSqlRelationalTableModel, QSqlQuery, {Model/View Programming},
285         {Table Model Example}, {Cached Table Example}
286 */
287
288 /*!
289     \fn QSqlTableModel::beforeDelete(int row)
290
291     This signal is emitted by deleteRowFromTable() before the \a row
292     is deleted from the currently active database table.
293 */
294
295 /*!
296     \fn void QSqlTableModel::primeInsert(int row, QSqlRecord &record)
297
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
302     values.
303 */
304
305 /*!
306     \fn QSqlTableModel::beforeInsert(QSqlRecord &record)
307
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.
312 */
313
314 /*!
315     \fn QSqlTableModel::beforeUpdate(int row, QSqlRecord &record)
316
317     This signal is emitted by updateRowInTable() before the \a row is
318     updated in the currently active database table with the values
319     from \a record.
320
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().
324
325     \sa QSqlRecord::isGenerated()
326 */
327
328 /*!
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.
332
333     The default edit strategy is \l OnRowChange.
334 */
335 QSqlTableModel::QSqlTableModel(QObject *parent, QSqlDatabase db)
336     : QSqlQueryModel(*new QSqlTableModelPrivate, parent)
337 {
338     Q_D(QSqlTableModel);
339     d->db = db.isValid() ? db : QSqlDatabase::database();
340 }
341
342 /*!  \internal
343 */
344 QSqlTableModel::QSqlTableModel(QSqlTableModelPrivate &dd, QObject *parent, QSqlDatabase db)
345     : QSqlQueryModel(dd, parent)
346 {
347     Q_D(QSqlTableModel);
348     d->db = db.isValid() ? db : QSqlDatabase::database();
349 }
350
351 /*!
352     Destroys the object and frees any allocated resources.
353 */
354 QSqlTableModel::~QSqlTableModel()
355 {
356 }
357
358 /*!
359     Sets the database table on which the model operates to \a
360     tableName. Does not select data from the table, but fetches its
361     field information.
362
363     To populate the model with the table's data, call select().
364
365     Error information can be retrieved with \l lastError().
366
367     \sa select(), setFilter(), lastError()
368 */
369 void QSqlTableModel::setTable(const QString &tableName)
370 {
371     Q_D(QSqlTableModel);
372     clear();
373     d->tableName = tableName;
374     d->initRecordAndPrimaryIndex();
375     d->initColOffsets(d->rec.count());
376
377     if (d->rec.count() == 0)
378         d->error = QSqlError(QLatin1String("Unable to find table ") + d->tableName, QString(),
379                              QSqlError::StatementError);
380 }
381
382 /*!
383     Returns the name of the currently selected table.
384 */
385 QString QSqlTableModel::tableName() const
386 {
387     Q_D(const QSqlTableModel);
388     return d->tableName;
389 }
390
391 /*!
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
394     returns false.
395
396     \note Calling select() will revert any unsubmitted changes and remove any inserted columns.
397
398     \sa setTable(), setFilter(), selectStatement()
399 */
400 bool QSqlTableModel::select()
401 {
402     Q_D(QSqlTableModel);
403     QString query = selectStatement();
404     if (query.isEmpty())
405         return false;
406
407     revertAll();
408     QSqlQuery qu(query, d->db);
409     setQuery(qu);
410
411     if (!qu.isActive() || lastError().isValid()) {
412         // something went wrong - revert to non-select state
413         d->initRecordAndPrimaryIndex();
414         return false;
415     }
416     return true;
417 }
418
419 /*!
420     \reimp
421 */
422 QVariant QSqlTableModel::data(const QModelIndex &index, int role) const
423 {
424     Q_D(const QSqlTableModel);
425     if (!index.isValid() || (role != Qt::DisplayRole && role != Qt::EditRole))
426         return QVariant();
427
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);
433
434     switch (d->strategy) {
435     case OnFieldChange:
436     case OnRowChange:
437         if (index.row() == d->insertIndex) {
438             QVariant val;
439             if (item.column() < 0 || item.column() >= d->rec.count())
440                 return val;
441             val = d->editBuffer.value(index.column());
442             if (val.type() == QVariant::Invalid)
443                 val = QVariant(d->rec.field(item.column()).type());
444             return val;
445         }
446         if (d->editIndex == item.row()) {
447             QVariant var = d->editBuffer.value(item.column());
448             if (var.isValid())
449                 return var;
450         }
451         break;
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)
456             return var;
457         break; }
458     }
459
460     // We need to handle row mapping here, but not column mapping
461     return QSqlQueryModel::data(index.sibling(item.row(), index.column()), role);
462 }
463
464 /*!
465     \reimp
466 */
467 QVariant QSqlTableModel::headerData(int section, Qt::Orientation orientation, int role) const
468 {
469     Q_D(const QSqlTableModel);
470     if (orientation == Qt::Vertical && role == Qt::DisplayRole) {
471         switch (d->strategy) {
472         case OnFieldChange:
473         case OnRowChange:
474             if (d->insertIndex == section)
475                 return QLatin1String("*");
476             break;
477         case OnManualSubmit:
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("!");
483             break;
484         }
485     }
486     return QSqlQueryModel::headerData(section, orientation, role);
487 }
488
489 /*!
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.
493
494     If \a index is invalid or points to a non-existing row, false is returned.
495 */
496 bool QSqlTableModel::isDirty(const QModelIndex &index) const
497 {
498     Q_D(const QSqlTableModel);
499     if (!index.isValid())
500         return false;
501
502     switch (d->strategy) {
503         case OnFieldChange:
504             return false;
505         case OnRowChange:
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());
513         }
514     }
515     return false;
516 }
517
518 /*!
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.
522
523     Returns true if the value could be set or false on error, for
524     example if \a index is out of bounds.
525
526     \sa editStrategy(), data(), submit(), submitAll(), revertRow()
527 */
528 bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
529 {
530     Q_D(QSqlTableModel);
531     if (role != Qt::EditRole)
532         return QSqlQueryModel::setData(index, value, role);
533
534     if (!index.isValid() || index.column() >= d->rec.count() || index.row() >= rowCount())
535         return false;
536
537     bool isOk = true;
538     switch (d->strategy) {
539     case OnFieldChange: {
540         if (index.row() == d->insertIndex) {
541             d->editBuffer.setValue(index.column(), value);
542             return true;
543         }
544         d->clearEditBuffer();
545         d->editBuffer.setValue(index.column(), value);
546         isOk = updateRowInTable(index.row(), d->editBuffer);
547         if (isOk)
548             select();
549         emit dataChanged(index, index);
550         break; }
551     case OnRowChange:
552         if (index.row() == d->insertIndex) {
553             d->editBuffer.setValue(index.column(), value);
554             return true;
555         }
556         if (d->editIndex != index.row()) {
557             if (d->editIndex != -1)
558                 submit();
559             d->clearEditBuffer();
560         }
561         d->editBuffer.setValue(index.column(), value);
562         d->editIndex = index.row();
563         emit dataChanged(index, index);
564         break;
565     case OnManualSubmit: {
566         QSqlTableModelPrivate::ModifiedRow &row = d->cache[index.row()];
567         if (row.op == QSqlTableModelPrivate::None) {
568             row.op = QSqlTableModelPrivate::Update;
569             row.rec = d->rec;
570             row.primaryValues = d->primaryValues(indexInQuery(index).row());
571         }
572         row.rec.setValue(index.column(), value);
573         emit dataChanged(index, index);
574         break; }
575     }
576     return isOk;
577 }
578
579 /*!
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.
583
584     \sa selectStatement()
585 */
586 void QSqlTableModel::setQuery(const QSqlQuery &query)
587 {
588     QSqlQueryModel::setQuery(query);
589 }
590
591 /*!
592     Updates the given \a row in the currently active database table
593     with the specified \a values. Returns true if successful; otherwise
594     returns false.
595
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
599     the database.
600
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().
604
605     \sa QSqlRecord::isGenerated(), setData()
606 */
607 bool QSqlTableModel::updateRowInTable(int row, const QSqlRecord &values)
608 {
609     Q_D(QSqlTableModel);
610     QSqlRecord rec(values);
611     emit beforeUpdate(row, rec);
612
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,
616                                                 rec, prepStatement);
617     QString where = d->db.driver()->sqlStatement(QSqlDriver::WhereStatement, d->tableName,
618                                                  whereValues, prepStatement);
619
620     if (stmt.isEmpty() || where.isEmpty() || row < 0 || row >= rowCount()) {
621         d->error = QSqlError(QLatin1String("No Fields to update"), QString(),
622                                  QSqlError::StatementError);
623         return false;
624     }
625     stmt.append(QLatin1Char(' ')).append(where);
626
627     return d->exec(stmt, prepStatement, rec, whereValues);
628 }
629
630
631 /*!
632     Inserts the values \a values into the currently active database table.
633
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.
638
639     Returns true if the values could be inserted, otherwise false.
640     Error information can be retrieved with \l lastError().
641
642     \sa lastError(), insertRow(), insertRows()
643 */
644 bool QSqlTableModel::insertRowIntoTable(const QSqlRecord &values)
645 {
646     Q_D(QSqlTableModel);
647     QSqlRecord rec = values;
648     emit beforeInsert(rec);
649
650     bool prepStatement = d->db.driver()->hasFeature(QSqlDriver::PreparedQueries);
651     QString stmt = d->db.driver()->sqlStatement(QSqlDriver::InsertStatement, d->tableName,
652                                                 rec, prepStatement);
653
654     if (stmt.isEmpty()) {
655         d->error = QSqlError(QLatin1String("No Fields to update"), QString(),
656                                  QSqlError::StatementError);
657         return false;
658     }
659
660     return d->exec(stmt, prepStatement, rec);
661 }
662
663 /*!
664     Deletes the given \a row from the currently active database table.
665
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.
670
671     Returns true if the row was deleted; otherwise returns false.
672
673     \sa removeRow(), removeRows()
674 */
675 bool QSqlTableModel::deleteRowFromTable(int row)
676 {
677     Q_D(QSqlTableModel);
678     emit beforeDelete(row);
679
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,
683                                                 d->tableName,
684                                                 QSqlRecord(),
685                                                 prepStatement);
686     QString where = d->db.driver()->sqlStatement(QSqlDriver::WhereStatement,
687                                                  d->tableName,
688                                                  whereValues,
689                                                  prepStatement);
690
691     if (stmt.isEmpty() || where.isEmpty()) {
692         d->error = QSqlError(QLatin1String("Unable to delete row"), QString(),
693                              QSqlError::StatementError);
694         return false;
695     }
696     stmt.append(QLatin1Char(' ')).append(where);
697
698     return d->exec(stmt, prepStatement, whereValues);
699 }
700
701 /*!
702     Submits all pending changes and returns true on success.
703     Returns false on error, detailed error information can be
704     obtained with lastError().
705
706     On success the model will be repopulated. Any views 
707     presenting it will lose their selections.
708
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
712     losing data.
713
714     \sa revertAll(), lastError()
715 */
716 bool QSqlTableModel::submitAll()
717 {
718     Q_D(QSqlTableModel);
719
720     switch (d->strategy) {
721     case OnFieldChange:
722         if (d->insertIndex == -1)
723             return true;
724         // else fall through
725     case OnRowChange:
726         if (d->editBuffer.isEmpty())
727             return true;
728         if (d->insertIndex != -1) {
729             if (!insertRowIntoTable(d->editBuffer))
730                 return false;
731             d->bottom = d->bottom.sibling(d->bottom.row() + 1, d->bottom.column());
732         } else {
733             if (!updateRowInTable(d->editIndex, d->editBuffer))
734                 return false;
735         }
736         d->clearEditBuffer();
737         d->editIndex = -1;
738         d->insertIndex = -1;
739         return select();
740     case OnManualSubmit:
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))
746                     return false;
747                 d->bottom = d->bottom.sibling(d->bottom.row() + 1, d->bottom.column());
748                 break;
749             case QSqlTableModelPrivate::Update:
750                 if (!updateRowInTable(it.key(), it.value().rec))
751                     return false;
752                 break;
753             case QSqlTableModelPrivate::Delete:
754                 if (!deleteRowFromTable(it.key()))
755                     return false;
756                 break;
757             case QSqlTableModelPrivate::None:
758                 Q_ASSERT_X(false, "QSqlTableModel::submitAll()", "Invalid cache operation");
759                 break;
760             }
761         }
762         d->clearCache();
763         return select();
764     }
765     return false;
766 }
767
768 /*!
769     This reimplemented slot is called by the item delegates when the
770     user stopped editing the current row.
771
772     Submits the currently edited row if the model's strategy is set
773     to OnRowChange or OnFieldChange. Does nothing for the OnManualSubmit
774     strategy.
775
776     Use submitAll() to submit all pending changes for the
777     OnManualSubmit strategy.
778
779     Returns true on success; otherwise returns false. Use lastError()
780     to query detailed error information.
781
782     On success the model will be repopulated. Any views 
783     presenting it will lose their selections.
784
785     \sa revert(), revertRow(), submitAll(), revertAll(), lastError()
786 */
787 bool QSqlTableModel::submit()
788 {
789     Q_D(QSqlTableModel);
790     if (d->strategy == OnRowChange || d->strategy == OnFieldChange)
791         return submitAll();
792     return true;
793 }
794
795 /*!
796     This reimplemented slot is called by the item delegates when the
797     user canceled editing the current row.
798
799     Reverts the changes if the model's strategy is set to
800     OnRowChange. Does nothing for the other edit strategies.
801
802     Use revertAll() to revert all pending changes for the
803     OnManualSubmit strategy or revertRow() to revert a specific row.
804
805     \sa submit(), submitAll(), revertRow(), revertAll()
806 */
807 void QSqlTableModel::revert()
808 {
809     Q_D(QSqlTableModel);
810     if (d->strategy == OnRowChange)
811         revertAll();
812 }
813
814 /*!
815     \enum QSqlTableModel::EditStrategy
816
817     This enum type describes which strategy to choose when editing values in the database.
818
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.
823
824     Note: To prevent inserting only partly initialized rows into the database,
825     \c OnFieldChange will behave like \c OnRowChange for newly inserted rows.
826
827     \sa setEditStrategy()
828 */
829
830
831 /*!
832     Sets the strategy for editing values in the database to \a
833     strategy.
834
835     This will revert any pending changes.
836
837     \sa editStrategy(), revertAll()
838 */
839 void QSqlTableModel::setEditStrategy(EditStrategy strategy)
840 {
841     Q_D(QSqlTableModel);
842     revertAll();
843     d->strategy = strategy;
844 }
845
846 /*!
847     Returns the current edit strategy.
848
849     \sa setEditStrategy()
850 */
851 QSqlTableModel::EditStrategy QSqlTableModel::editStrategy() const
852 {
853     Q_D(const QSqlTableModel);
854     return d->strategy;
855 }
856
857 /*!
858     Reverts all pending changes.
859
860     \sa revert(), revertRow(), submitAll()
861 */
862 void QSqlTableModel::revertAll()
863 {
864     Q_D(QSqlTableModel);
865     switch (d->strategy) {
866     case OnFieldChange:
867         break;
868     case OnRowChange:
869         if (d->editIndex != -1)
870             revertRow(d->editIndex);
871         else if (d->insertIndex != -1)
872             revertRow(d->insertIndex);
873         break;
874     case OnManualSubmit:
875         while (!d->cache.isEmpty())
876             revertRow(d->cache.constBegin().key());
877         break;
878     }
879 }
880
881 /*!
882     Reverts all changes for the specified \a row.
883
884     \sa revert(), revertAll(), submit(), submitAll()
885 */
886 void QSqlTableModel::revertRow(int row)
887 {
888     if (row < 0)
889         return;
890
891     Q_D(QSqlTableModel);
892     switch (d->strategy) {
893     case OnFieldChange:
894         break;
895     case OnRowChange: {
896         if (d->editIndex == row) {
897             d->editBuffer.clear();
898             int oldIndex = d->editIndex;
899             d->editIndex = -1;
900             emit dataChanged(createIndex(oldIndex, 0), createIndex(oldIndex, columnCount()));
901         } else if (d->insertIndex == row) {
902             d->revertInsertedRow();
903         }
904         break; }
905     case OnManualSubmit:
906         d->revertCachedRow(row);
907         break;
908     }
909 }
910
911 /*!
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.
914
915     \sa setTable(), setPrimaryKey(), QSqlDatabase::primaryIndex()
916 */
917 QSqlIndex QSqlTableModel::primaryKey() const
918 {
919     Q_D(const QSqlTableModel);
920     return d->primaryIndex;
921 }
922
923 /*!
924     Protected method that allows subclasses to set the primary key to
925     \a key.
926
927     Normally, the primary index is set automatically whenever you
928     call setTable().
929
930     \sa primaryKey(), QSqlDatabase::primaryIndex()
931 */
932 void QSqlTableModel::setPrimaryKey(const QSqlIndex &key)
933 {
934     Q_D(QSqlTableModel);
935     d->primaryIndex = key;
936 }
937
938 /*!
939     Returns a pointer to the used QSqlDatabase or 0 if no database was set.
940 */
941 QSqlDatabase QSqlTableModel::database() const
942 {
943     Q_D(const QSqlTableModel);
944      return d->db;
945 }
946
947 /*!
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.
951
952     \sa setSort(), select(), orderByClause()
953 */
954 void QSqlTableModel::sort(int column, Qt::SortOrder order)
955 {
956     setSort(column, order);
957     select();
958 }
959
960 /*!
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().
964
965     \sa select(), orderByClause()
966 */
967 void QSqlTableModel::setSort(int column, Qt::SortOrder order)
968 {
969     Q_D(QSqlTableModel);
970     d->sortColumn = column;
971     d->sortOrder = order;
972 }
973
974 /*!
975     Returns an SQL \c{ORDER BY} clause based on the currently set
976     sort order.
977
978     \sa setSort(), selectStatement()
979 */
980 QString QSqlTableModel::orderByClause() const
981 {
982     Q_D(const QSqlTableModel);
983     QString s;
984     QSqlField f = d->rec.field(d->sortColumn);
985     if (!f.isValid())
986         return s;
987         
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");
994
995     return s;
996 }
997
998 /*!
999     Returns the index of the field \a fieldName.
1000 */
1001 int QSqlTableModel::fieldIndex(const QString &fieldName) const
1002 {
1003     Q_D(const QSqlTableModel);
1004     return d->rec.indexOf(fieldName);
1005 }
1006
1007 /*!
1008     Returns the SQL \c SELECT statement used internally to populate
1009     the model. The statement includes the filter and the \c{ORDER BY}
1010     clause.
1011
1012     \sa filter(), orderByClause()
1013 */
1014 QString QSqlTableModel::selectStatement() const
1015 {
1016     Q_D(const QSqlTableModel);
1017     QString query;
1018     if (d->tableName.isEmpty()) {
1019         d->error = QSqlError(QLatin1String("No table name given"), QString(),
1020                              QSqlError::StatementError);
1021         return query;
1022     }
1023     if (d->rec.isEmpty()) {
1024         d->error = QSqlError(QLatin1String("Unable to find table ") + d->tableName, QString(),
1025                              QSqlError::StatementError);
1026         return query;
1027     }
1028
1029     query = d->db.driver()->sqlStatement(QSqlDriver::SelectStatement,
1030                                          d->tableName,
1031                                          d->rec,
1032                                          false);
1033     if (query.isEmpty()) {
1034         d->error = QSqlError(QLatin1String("Unable to select fields from table ") + d->tableName,
1035                              QString(), QSqlError::StatementError);
1036         return query;
1037     }
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);
1043
1044     return query;
1045 }
1046
1047 /*!
1048     Removes \a count columns from the \a parent model, starting at
1049     index \a column.
1050
1051     Returns if the columns were successfully removed; otherwise
1052     returns false.
1053
1054     \sa removeRows()
1055 */
1056 bool QSqlTableModel::removeColumns(int column, int count, const QModelIndex &parent)
1057 {
1058     Q_D(QSqlTableModel);
1059     if (parent.isValid() || column < 0 || column + count > d->rec.count())
1060         return false;
1061     for (int i = 0; i < count; ++i)
1062         d->rec.remove(column);
1063     if (d->query.isActive())
1064         return select();
1065     return true;
1066 }
1067
1068 /*!
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.
1072
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.
1076
1077     Returns true if all rows could be removed; otherwise returns
1078     false. Detailed error information can be retrieved using
1079     lastError().
1080
1081     \sa removeColumns(), insertRows()
1082 */
1083 bool QSqlTableModel::removeRows(int row, int count, const QModelIndex &parent)
1084 {
1085     Q_D(QSqlTableModel);
1086     if (parent.isValid() || row < 0 || count <= 0)
1087         return false;
1088
1089     int i;
1090     switch (d->strategy) {
1091     case OnFieldChange:
1092     case OnRowChange:
1093         for (i = 0; i < count; ++i) {
1094             if (row + i == d->insertIndex)
1095                 d->revertInsertedRow();
1096             else if (!deleteRowFromTable(row + i))
1097                 return false;
1098         }
1099         select();
1100         break;
1101     case OnManualSubmit:
1102         for (i = 0; i < count; ++i) {
1103             int idx = row + i;
1104             if (idx >= rowCount())
1105                 return false;
1106             if (d->cache.value(idx).op == QSqlTableModelPrivate::Insert)
1107                 revertRow(idx);
1108             else {
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);
1112             }
1113         }
1114         break;
1115     }
1116     return true;
1117 }
1118
1119 /*!
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.
1123
1124     Only one row at a time can be inserted when using the
1125     OnFieldChange or OnRowChange update strategies.
1126
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
1129     values.
1130
1131     Returns false if the parameters are out of bounds; otherwise
1132     returns true.
1133
1134     \sa primeInsert(), insertRecord()
1135 */
1136 bool QSqlTableModel::insertRows(int row, int count, const QModelIndex &parent)
1137 {
1138     Q_D(QSqlTableModel);
1139     if (row < 0 || count <= 0 || row > rowCount() || parent.isValid())
1140         return false;
1141
1142     switch (d->strategy) {
1143     case OnFieldChange:
1144     case OnRowChange:
1145         if (count != 1)
1146             return false;
1147         beginInsertRows(parent, row, row);
1148         d->insertIndex = row;
1149         // ### apply dangling changes...
1150         d->clearEditBuffer();
1151         emit primeInsert(row, d->editBuffer);
1152         break;
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();
1160                 d->cache.erase(it);
1161                 it = d->cache.insert(oldKey + count, oldValue);
1162             }
1163         }
1164
1165         for (int i = 0; i < count; ++i) {
1166             d->cache[row + i] = QSqlTableModelPrivate::ModifiedRow(QSqlTableModelPrivate::Insert,
1167                                                                    d->rec);
1168             emit primeInsert(row + i, d->cache[row + i].rec);
1169         }
1170         break;
1171     }
1172     endInsertRows();
1173     return true;
1174 }
1175
1176 /*!
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.
1180
1181     Returns true if the row could be inserted, otherwise false.
1182
1183     \sa insertRows(), removeRows()
1184 */
1185 bool QSqlTableModel::insertRecord(int row, const QSqlRecord &record)
1186 {
1187     Q_D(QSqlTableModel);
1188     if (row < 0)
1189         row = rowCount();
1190     if (!insertRow(row, QModelIndex()))
1191         return false;
1192     if (!setRecord(row, record))
1193         return false;
1194     if (d->strategy == OnFieldChange || d->strategy == OnRowChange)
1195         return submit();
1196     return true;
1197 }
1198
1199 /*! \reimp
1200 */
1201 int QSqlTableModel::rowCount(const QModelIndex &parent) const
1202 {
1203     Q_D(const QSqlTableModel);
1204
1205     if (parent.isValid())
1206         return 0;
1207
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)
1213                  ++rc;
1214         }
1215     } else if (d->insertIndex >= 0) {
1216         ++rc;
1217     }
1218     return rc;
1219 }
1220
1221 /*!
1222     Returns the index of the value in the database result set for the
1223     given \a item in the model.
1224
1225     The return value is identical to \a item if no columns or rows
1226     have been inserted, removed, or moved around.
1227
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.
1230
1231     \sa QSqlQueryModel::indexInQuery()
1232 */
1233 QModelIndex QSqlTableModel::indexInQuery(const QModelIndex &item) const
1234 {
1235     Q_D(const QSqlTableModel);
1236     const QModelIndex it = QSqlQueryModel::indexInQuery(item); // this adjusts columns only
1237     if (d->strategy == OnManualSubmit) {
1238         int rowOffset = 0;
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)
1242                 ++rowOffset;
1243             ++i;
1244         }
1245         return createIndex(it.row() - rowOffset, it.column(), it.internalPointer());
1246     } else {
1247         if (d->insertIndex >= 0 && it.row() >= d->insertIndex)
1248             return createIndex(it.row() - 1, it.column(), it.internalPointer());
1249     }
1250     return it;
1251 }
1252
1253 /*!
1254     Returns the currently set filter.
1255
1256     \sa setFilter(), select()
1257 */
1258 QString QSqlTableModel::filter() const
1259 {
1260     Q_D(const QSqlTableModel);
1261     return d->filter;
1262 }
1263
1264 /*!
1265     Sets the current filter to \a filter.
1266
1267     The filter is a SQL \c WHERE clause without the keyword \c WHERE
1268     (for example, \c{name='Josephine')}.
1269
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.
1273
1274     \sa filter(), select(), selectStatement(), orderByClause()
1275 */
1276 void QSqlTableModel::setFilter(const QString &filter)
1277 {
1278     Q_D(QSqlTableModel);
1279     d->filter = filter;
1280     if (d->query.isActive())
1281         select();
1282 }
1283
1284 /*! \reimp
1285 */
1286 void QSqlTableModel::clear()
1287 {
1288     Q_D(QSqlTableModel);
1289     d->clear();
1290     QSqlQueryModel::clear();
1291 }
1292
1293 /*! \reimp
1294 */
1295 Qt::ItemFlags QSqlTableModel::flags(const QModelIndex &index) const
1296 {
1297     Q_D(const QSqlTableModel);
1298     if (index.internalPointer() || index.column() < 0 || index.column() >= d->rec.count()
1299         || index.row() < 0)
1300         return 0;
1301     if (d->rec.field(index.column()).isReadOnly())
1302         return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
1303     return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
1304 }
1305
1306 /*!
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
1309     returns false.
1310
1311     \sa record()
1312 */
1313 bool QSqlTableModel::setRecord(int row, const QSqlRecord &record)
1314 {
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())
1318         return false;
1319
1320     bool isOk = true;
1321     switch (d->strategy) {
1322     case OnFieldChange:
1323     case OnRowChange:
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;
1329             mrow.rec = d->rec;
1330             mrow.primaryValues = d->primaryValues(indexInQuery(createIndex(row, 0)).row());
1331         }
1332         QString fieldName;
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);
1338             if (idx == -1)
1339                 isOk = false;
1340             else
1341                 mrow.rec.setValue(idx, record.value(i));
1342         }
1343
1344         if (isOk)
1345             emit dataChanged(createIndex(row, 0), createIndex(row, columnCount() - 1));
1346         return isOk; }
1347     }
1348     return false;
1349 }
1350
1351 QT_END_NAMESPACE