summaryrefslogtreecommitdiffstats
path: root/tests/auto/sql/models
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/sql/models')
-rw-r--r--tests/auto/sql/models/models.pro6
-rw-r--r--tests/auto/sql/models/qsqlquerymodel/.gitignore1
-rw-r--r--tests/auto/sql/models/qsqlquerymodel/qsqlquerymodel.pro20
-rw-r--r--tests/auto/sql/models/qsqlquerymodel/tst_qsqlquerymodel.cpp641
-rw-r--r--tests/auto/sql/models/qsqlrelationaltablemodel/.gitignore1
-rw-r--r--tests/auto/sql/models/qsqlrelationaltablemodel/qsqlrelationaltablemodel.pro25
-rw-r--r--tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp1494
-rw-r--r--tests/auto/sql/models/qsqltablemodel/.gitignore1
-rw-r--r--tests/auto/sql/models/qsqltablemodel/qsqltablemodel.pro22
-rw-r--r--tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp1377
10 files changed, 3588 insertions, 0 deletions
diff --git a/tests/auto/sql/models/models.pro b/tests/auto/sql/models/models.pro
new file mode 100644
index 0000000000..d04ba01710
--- /dev/null
+++ b/tests/auto/sql/models/models.pro
@@ -0,0 +1,6 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qsqlquerymodel \
+ qsqlrelationaltablemodel \
+ qsqltablemodel \
+
diff --git a/tests/auto/sql/models/qsqlquerymodel/.gitignore b/tests/auto/sql/models/qsqlquerymodel/.gitignore
new file mode 100644
index 0000000000..e5ff8accf6
--- /dev/null
+++ b/tests/auto/sql/models/qsqlquerymodel/.gitignore
@@ -0,0 +1 @@
+tst_qsqlquerymodel
diff --git a/tests/auto/sql/models/qsqlquerymodel/qsqlquerymodel.pro b/tests/auto/sql/models/qsqlquerymodel/qsqlquerymodel.pro
new file mode 100644
index 0000000000..0664bae6e9
--- /dev/null
+++ b/tests/auto/sql/models/qsqlquerymodel/qsqlquerymodel.pro
@@ -0,0 +1,20 @@
+load(qttest_p4)
+SOURCES += tst_qsqlquerymodel.cpp
+
+QT += widgets sql
+
+wince*: {
+ DEPLOYMENT_PLUGIN += qsqlite
+ LIBS += -lws2
+}else:symbian {
+ qt_not_deployed {
+ contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2)|contains(S60_VERSION, 5.0) {
+ sqlite.path = /sys/bin
+ sqlite.files = sqlite3.dll
+ DEPLOYMENT += sqlite
+ }
+ }
+} else {
+ win32:LIBS += -lws2_32
+}
+
diff --git a/tests/auto/sql/models/qsqlquerymodel/tst_qsqlquerymodel.cpp b/tests/auto/sql/models/qsqlquerymodel/tst_qsqlquerymodel.cpp
new file mode 100644
index 0000000000..fabba48d7c
--- /dev/null
+++ b/tests/auto/sql/models/qsqlquerymodel/tst_qsqlquerymodel.cpp
@@ -0,0 +1,641 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGui>
+
+#include <qsqldriver.h>
+#include <qsqldatabase.h>
+#include <qsqlerror.h>
+#include <qsqlfield.h>
+#include <qsqlquery.h>
+#include <qsqlrecord.h>
+
+#include <qsqlquerymodel.h>
+#include <qsortfilterproxymodel.h>
+
+#include "../../kernel/qsqldatabase/tst_databases.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+Q_DECLARE_METATYPE(Qt::Orientation)
+
+class tst_QSqlQueryModel : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QSqlQueryModel();
+ virtual ~tst_QSqlQueryModel();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void insertColumn_data() { generic_data(); }
+ void insertColumn();
+ void removeColumn_data() { generic_data(); }
+ void removeColumn();
+ void record_data() { generic_data(); }
+ void record();
+ void setHeaderData_data() { generic_data(); }
+ void setHeaderData();
+ void fetchMore_data() { generic_data(); }
+ void fetchMore();
+
+ //problem specific tests
+ void withSortFilterProxyModel_data() { generic_data(); }
+ void withSortFilterProxyModel();
+ void setQuerySignalEmission_data() { generic_data(); }
+ void setQuerySignalEmission();
+ void setQueryWithNoRowsInResultSet_data() { generic_data(); }
+ void setQueryWithNoRowsInResultSet();
+
+ void task_180617();
+ void task_180617_data() { generic_data(); }
+ void task_QTBUG_4963_setHeaderDataWithProxyModel();
+
+private:
+ void generic_data(const QString &engine=QString());
+ void dropTestTables(QSqlDatabase db);
+ void createTestTables(QSqlDatabase db);
+ void populateTestTables(QSqlDatabase db);
+ tst_Databases dbs;
+};
+
+/* Stupid class that makes protected members public for testing */
+class DBTestModel: public QSqlQueryModel
+{
+public:
+ DBTestModel(QObject *parent = 0): QSqlQueryModel(parent) {}
+ QModelIndex indexInQuery(const QModelIndex &item) const { return QSqlQueryModel::indexInQuery(item); }
+};
+
+tst_QSqlQueryModel::tst_QSqlQueryModel()
+{
+}
+
+tst_QSqlQueryModel::~tst_QSqlQueryModel()
+{
+}
+
+void tst_QSqlQueryModel::initTestCase()
+{
+ qRegisterMetaType<QModelIndex>("QModelIndex");
+ dbs.open();
+ for (QStringList::ConstIterator it = dbs.dbNames.begin(); it != dbs.dbNames.end(); ++it) {
+ QSqlDatabase db = QSqlDatabase::database((*it));
+ CHECK_DATABASE(db);
+ dropTestTables(db); //in case of leftovers
+ createTestTables(db);
+ populateTestTables(db);
+ }
+}
+
+void tst_QSqlQueryModel::cleanupTestCase()
+{
+ for (QStringList::ConstIterator it = dbs.dbNames.begin(); it != dbs.dbNames.end(); ++it) {
+ QSqlDatabase db = QSqlDatabase::database((*it));
+ CHECK_DATABASE(db);
+ dropTestTables(db);
+ }
+ dbs.close();
+}
+
+void tst_QSqlQueryModel::dropTestTables(QSqlDatabase db)
+{
+ QStringList tableNames;
+ tableNames << qTableName("test", __FILE__)
+ << qTableName("test2", __FILE__)
+ << qTableName("test3", __FILE__)
+ << qTableName("many", __FILE__);
+ tst_Databases::safeDropTables(db, tableNames);
+}
+
+void tst_QSqlQueryModel::createTestTables(QSqlDatabase db)
+{
+ dropTestTables(db);
+ QSqlQuery q(db);
+ if(tst_Databases::isPostgreSQL(db))
+ QVERIFY_SQL( q, exec("set client_min_messages='warning'"));
+ QVERIFY_SQL( q, exec("create table " + qTableName("test", __FILE__) + "(id integer not null, name varchar(20), title integer, primary key (id))"));
+ QVERIFY_SQL( q, exec("create table " + qTableName("test2", __FILE__) + "(id integer not null, title varchar(20), primary key (id))"));
+ QVERIFY_SQL( q, exec("create table " + qTableName("test3", __FILE__) + "(id integer not null, primary key (id))"));
+ QVERIFY_SQL( q, exec("create table " + qTableName("many", __FILE__) + "(id integer not null, name varchar(20), primary key (id))"));
+}
+
+void tst_QSqlQueryModel::populateTestTables(QSqlDatabase db)
+{
+ qWarning() << "Populating test tables, this can take quite a while... ZZZzzz...";
+ bool hasTransactions = db.driver()->hasFeature(QSqlDriver::Transactions);
+
+ QSqlQuery q(db), q2(db);
+
+ tst_Databases::safeDropTables(db, QStringList() << qTableName("manytmp", __FILE__) << qTableName("test3tmp", __FILE__));
+ QVERIFY_SQL(q, exec("create table " + qTableName("manytmp", __FILE__) + "(id integer not null, name varchar(20), primary key (id))"));
+ QVERIFY_SQL(q, exec("create table " + qTableName("test3tmp", __FILE__) + "(id integer not null, primary key (id))"));
+
+ if (hasTransactions) QVERIFY_SQL(db, transaction());
+
+ QVERIFY_SQL(q, exec("insert into " + qTableName("test", __FILE__) + " values(1, 'harry', 1)"));
+ QVERIFY_SQL(q, exec("insert into " + qTableName("test", __FILE__) + " values(2, 'trond', 2)"));
+ QVERIFY_SQL(q, exec("insert into " + qTableName("test2", __FILE__) + " values(1, 'herr')"));
+ QVERIFY_SQL(q, exec("insert into " + qTableName("test2", __FILE__) + " values(2, 'mister')"));
+
+ QVERIFY_SQL(q, exec(QString("insert into " + qTableName("test3", __FILE__) + " values(0)")));
+ QVERIFY_SQL(q, prepare("insert into "+qTableName("test3", __FILE__)+"(id) select id + ? from "+qTableName("test3tmp", __FILE__)));
+ for (int i=1; i<260; i*=2) {
+ q2.exec("delete from "+qTableName("test3tmp", __FILE__));
+ QVERIFY_SQL(q2, exec("insert into "+qTableName("test3tmp", __FILE__)+"(id) select id from "+qTableName("test3", __FILE__)));
+ q.bindValue(0, i);
+ QVERIFY_SQL(q, exec());
+ }
+
+ QVERIFY_SQL(q, exec(QString("insert into " + qTableName("many", __FILE__) + "(id, name) values (0, \'harry\')")));
+ QVERIFY_SQL(q, prepare("insert into "+qTableName("many", __FILE__)+"(id, name) select id + ?, name from "+qTableName("manytmp", __FILE__)));
+ for (int i=1; i < 2048; i*=2) {
+ q2.exec("delete from "+qTableName("manytmp", __FILE__));
+ QVERIFY_SQL(q2, exec("insert into "+qTableName("manytmp", __FILE__)+"(id, name) select id, name from "+qTableName("many", __FILE__)));
+ q.bindValue(0, i);
+ QVERIFY_SQL(q, exec());
+ }
+
+ if (hasTransactions) QVERIFY_SQL(db, commit());
+
+ tst_Databases::safeDropTables(db, QStringList() << qTableName("manytmp", __FILE__) << qTableName("test3tmp", __FILE__));
+}
+
+void tst_QSqlQueryModel::generic_data(const QString& engine)
+{
+ if ( dbs.fillTestTable(engine) == 0 ) {
+ if(engine.isEmpty())
+ QSKIP( "No database drivers are available in this Qt configuration", SkipAll );
+ else
+ QSKIP( (QString("No database drivers of type %1 are available in this Qt configuration").arg(engine)).toLocal8Bit(), SkipAll );
+ }
+}
+
+void tst_QSqlQueryModel::init()
+{
+}
+
+void tst_QSqlQueryModel::cleanup()
+{
+}
+
+void tst_QSqlQueryModel::removeColumn()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ DBTestModel model;
+ model.setQuery(QSqlQuery("select * from " + qTableName("test", __FILE__), db));
+ model.fetchMore();
+ QSignalSpy spy(&model, SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int)));
+
+ QCOMPARE(model.columnCount(), 3);
+ QVERIFY(model.removeColumn(0));
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(*(QModelIndex *)spy.at(0).at(0).constData() == QModelIndex());
+ QCOMPARE(spy.at(0).at(1).toInt(), 0);
+ QCOMPARE(spy.at(0).at(2).toInt(), 0);
+
+ QCOMPARE(model.columnCount(), 2);
+ QCOMPARE(model.indexInQuery(model.index(0, 0)).column(), 1);
+ QCOMPARE(model.indexInQuery(model.index(0, 1)).column(), 2);
+ QCOMPARE(model.indexInQuery(model.index(0, 2)).column(), -1);
+ QCOMPARE(model.indexInQuery(model.index(0, 3)).column(), -1);
+
+ QVERIFY(model.insertColumn(1));
+ QCOMPARE(model.columnCount(), 3);
+ QCOMPARE(model.indexInQuery(model.index(0, 0)).column(), 1);
+ QCOMPARE(model.indexInQuery(model.index(0, 1)).column(), -1);
+ QCOMPARE(model.indexInQuery(model.index(0, 2)).column(), 2);
+ QCOMPARE(model.indexInQuery(model.index(0, 3)).column(), -1);
+
+ QCOMPARE(model.data(model.index(0, 0)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 1)), QVariant());
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 3)), QVariant());
+
+ QVERIFY(!model.removeColumn(42));
+ QVERIFY(!model.removeColumn(3));
+ QVERIFY(!model.removeColumn(1, model.index(1, 2)));
+ QCOMPARE(model.columnCount(), 3);
+
+ QVERIFY(model.removeColumn(2));
+
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(*(QModelIndex *)spy.at(1).at(0).constData() == QModelIndex());
+ QCOMPARE(spy.at(1).at(1).toInt(), 2);
+ QCOMPARE(spy.at(1).at(2).toInt(), 2);
+
+ QCOMPARE(model.columnCount(), 2);
+ QCOMPARE(model.indexInQuery(model.index(0, 0)).column(), 1);
+ QCOMPARE(model.indexInQuery(model.index(0, 1)).column(), -1);
+ QCOMPARE(model.indexInQuery(model.index(0, 2)).column(), -1);
+ QCOMPARE(model.indexInQuery(model.index(0, 3)).column(), -1);
+
+ QVERIFY(model.removeColumn(1));
+
+ QCOMPARE(spy.count(), 3);
+ QVERIFY(*(QModelIndex *)spy.at(2).at(0).constData() == QModelIndex());
+ QCOMPARE(spy.at(2).at(1).toInt(), 1);
+ QCOMPARE(spy.at(2).at(2).toInt(), 1);
+
+ QCOMPARE(model.columnCount(), 1);
+ QCOMPARE(model.indexInQuery(model.index(0, 0)).column(), 1);
+ QCOMPARE(model.indexInQuery(model.index(0, 1)).column(), -1);
+ QCOMPARE(model.indexInQuery(model.index(0, 2)).column(), -1);
+ QCOMPARE(model.indexInQuery(model.index(0, 3)).column(), -1);
+ QCOMPARE(model.data(model.index(0, 0)).toString(), QString("harry"));
+
+ QVERIFY(model.removeColumn(0));
+
+ QCOMPARE(spy.count(), 4);
+ QVERIFY(*(QModelIndex *)spy.at(3).at(0).constData() == QModelIndex());
+ QCOMPARE(spy.at(3).at(1).toInt(), 0);
+ QCOMPARE(spy.at(3).at(2).toInt(), 0);
+
+ QCOMPARE(model.columnCount(), 0);
+ QCOMPARE(model.indexInQuery(model.index(0, 0)).column(), -1);
+ QCOMPARE(model.indexInQuery(model.index(0, 1)).column(), -1);
+ QCOMPARE(model.indexInQuery(model.index(0, 2)).column(), -1);
+ QCOMPARE(model.indexInQuery(model.index(0, 3)).column(), -1);
+}
+
+void tst_QSqlQueryModel::insertColumn()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ DBTestModel model;
+ model.setQuery(QSqlQuery("select * from " + qTableName("test", __FILE__), db));
+ model.fetchMore(); // necessary???
+
+ bool isToUpper = db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2");
+ const QString idColumn(isToUpper ? "ID" : "id");
+ const QString nameColumn(isToUpper ? "NAME" : "name");
+ const QString titleColumn(isToUpper ? "TITLE" : "title");
+
+ QSignalSpy spy(&model, SIGNAL(columnsInserted(QModelIndex, int, int)));
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 3)), QVariant());
+
+ QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), idColumn);
+ QCOMPARE(model.headerData(1, Qt::Horizontal).toString(), nameColumn);
+ QCOMPARE(model.headerData(2, Qt::Horizontal).toString(), titleColumn);
+ QCOMPARE(model.headerData(3, Qt::Horizontal).toString(), QString("4"));
+
+ QVERIFY(model.insertColumn(1));
+
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(*(QModelIndex *)spy.at(0).at(0).constData() == QModelIndex());
+ QCOMPARE(spy.at(0).at(1).toInt(), 1);
+ QCOMPARE(spy.at(0).at(2).toInt(), 1);
+
+ QCOMPARE(model.indexInQuery(model.index(0, 0)).column(), 0);
+ QCOMPARE(model.indexInQuery(model.index(0, 1)).column(), -1);
+ QCOMPARE(model.indexInQuery(model.index(0, 2)).column(), 1);
+ QCOMPARE(model.indexInQuery(model.index(0, 3)).column(), 2);
+ QCOMPARE(model.indexInQuery(model.index(0, 4)).column(), -1);
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)), QVariant());
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 3)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 4)), QVariant());
+
+ QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), idColumn);
+ QCOMPARE(model.headerData(1, Qt::Horizontal).toString(), QString("2"));
+ QCOMPARE(model.headerData(2, Qt::Horizontal).toString(), nameColumn);
+ QCOMPARE(model.headerData(3, Qt::Horizontal).toString(), titleColumn);
+ QCOMPARE(model.headerData(4, Qt::Horizontal).toString(), QString("5"));
+
+ QVERIFY(!model.insertColumn(-1));
+ QVERIFY(!model.insertColumn(100));
+ QVERIFY(!model.insertColumn(1, model.index(1, 1)));
+
+ QVERIFY(model.insertColumn(0));
+
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(*(QModelIndex *)spy.at(1).at(0).constData() == QModelIndex());
+ QCOMPARE(spy.at(1).at(1).toInt(), 0);
+ QCOMPARE(spy.at(1).at(2).toInt(), 0);
+
+ QCOMPARE(model.indexInQuery(model.index(0, 0)).column(), -1);
+ QCOMPARE(model.indexInQuery(model.index(0, 1)).column(), 0);
+ QCOMPARE(model.indexInQuery(model.index(0, 2)).column(), -1);
+ QCOMPARE(model.indexInQuery(model.index(0, 3)).column(), 1);
+ QCOMPARE(model.indexInQuery(model.index(0, 4)).column(), 2);
+ QCOMPARE(model.indexInQuery(model.index(0, 5)).column(), -1);
+
+ QVERIFY(!model.insertColumn(6));
+ QVERIFY(model.insertColumn(5));
+
+ QCOMPARE(spy.count(), 3);
+ QVERIFY(*(QModelIndex *)spy.at(2).at(0).constData() == QModelIndex());
+ QCOMPARE(spy.at(2).at(1).toInt(), 5);
+ QCOMPARE(spy.at(2).at(2).toInt(), 5);
+
+ QCOMPARE(model.indexInQuery(model.index(0, 0)).column(), -1);
+ QCOMPARE(model.indexInQuery(model.index(0, 1)).column(), 0);
+ QCOMPARE(model.indexInQuery(model.index(0, 2)).column(), -1);
+ QCOMPARE(model.indexInQuery(model.index(0, 3)).column(), 1);
+ QCOMPARE(model.indexInQuery(model.index(0, 4)).column(), 2);
+ QCOMPARE(model.indexInQuery(model.index(0, 5)).column(), -1);
+ QCOMPARE(model.indexInQuery(model.index(0, 6)).column(), -1);
+
+ QCOMPARE(model.record().field(0).name(), QString());
+ QCOMPARE(model.record().field(1).name(), idColumn);
+ QCOMPARE(model.record().field(2).name(), QString());
+ QCOMPARE(model.record().field(3).name(), nameColumn);
+ QCOMPARE(model.record().field(4).name(), titleColumn);
+ QCOMPARE(model.record().field(5).name(), QString());
+ QCOMPARE(model.record().field(6).name(), QString());
+
+ QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), QString("1"));
+ QCOMPARE(model.headerData(1, Qt::Horizontal).toString(), idColumn);
+ QCOMPARE(model.headerData(2, Qt::Horizontal).toString(), QString("3"));
+ QCOMPARE(model.headerData(3, Qt::Horizontal).toString(), nameColumn);
+ QCOMPARE(model.headerData(4, Qt::Horizontal).toString(), titleColumn);
+ QCOMPARE(model.headerData(5, Qt::Horizontal).toString(), QString("6"));
+ QCOMPARE(model.headerData(6, Qt::Horizontal).toString(), QString("7"));
+}
+
+void tst_QSqlQueryModel::record()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlQueryModel model;
+ model.setQuery(QSqlQuery("select * from " + qTableName("test", __FILE__), db));
+
+ QSqlRecord rec = model.record();
+
+ bool isToUpper = db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2");
+
+ QCOMPARE(rec.count(), 3);
+ QCOMPARE(rec.fieldName(0), isToUpper ? QString("ID") : QString("id"));
+ QCOMPARE(rec.fieldName(1), isToUpper ? QString("NAME") : QString("name"));
+ QCOMPARE(rec.fieldName(2), isToUpper ? QString("TITLE") : QString("title"));
+ QCOMPARE(rec.value(0), QVariant(rec.field(0).type()));
+ QCOMPARE(rec.value(1), QVariant(rec.field(1).type()));
+ QCOMPARE(rec.value(2), QVariant(rec.field(2).type()));
+
+ rec = model.record(0);
+ QCOMPARE(rec.fieldName(0), isToUpper ? QString("ID") : QString("id"));
+ QCOMPARE(rec.fieldName(1), isToUpper ? QString("NAME") : QString("name"));
+ QCOMPARE(rec.fieldName(2), isToUpper ? QString("TITLE") : QString("title"));
+ QCOMPARE(rec.value(0).toString(), QString("1"));
+ QCOMPARE(rec.value(1), QVariant("harry"));
+ QCOMPARE(rec.value(2), QVariant(1));
+}
+
+void tst_QSqlQueryModel::setHeaderData()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlQueryModel model;
+
+ QVERIFY(!model.setHeaderData(5, Qt::Vertical, "foo"));
+ QVERIFY(model.headerData(5, Qt::Vertical).isValid());
+
+ model.setQuery(QSqlQuery("select * from " + qTableName("test", __FILE__), db));
+
+ qRegisterMetaType<Qt::Orientation>("Qt::Orientation");
+ QSignalSpy spy(&model, SIGNAL(headerDataChanged(Qt::Orientation, int, int)));
+ QVERIFY(model.setHeaderData(2, Qt::Horizontal, "bar"));
+ QCOMPARE(model.headerData(2, Qt::Horizontal).toString(), QString("bar"));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(qvariant_cast<Qt::Orientation>(spy.value(0).value(0)), Qt::Horizontal);
+ QCOMPARE(spy.value(0).value(1).toInt(), 2);
+ QCOMPARE(spy.value(0).value(2).toInt(), 2);
+
+ QVERIFY(!model.setHeaderData(7, Qt::Horizontal, "foo", Qt::ToolTipRole));
+ QVERIFY(!model.headerData(7, Qt::Horizontal, Qt::ToolTipRole).isValid());
+
+ bool isToUpper = db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2");
+ QCOMPARE(model.headerData(0, Qt::Horizontal).toString(), isToUpper ? QString("ID") : QString("id"));
+ QCOMPARE(model.headerData(1, Qt::Horizontal).toString(), isToUpper ? QString("NAME") : QString("name"));
+ QCOMPARE(model.headerData(2, Qt::Horizontal).toString(), QString("bar"));
+ QVERIFY(model.headerData(3, Qt::Horizontal).isValid());
+}
+
+void tst_QSqlQueryModel::fetchMore()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlQueryModel model;
+ QSignalSpy spy(&model, SIGNAL(rowsInserted(QModelIndex, int, int)));
+
+ model.setQuery(QSqlQuery("select * from " + qTableName("many", __FILE__), db));
+ int rowCount = model.rowCount();
+
+ QCOMPARE(spy.value(0).value(1).toInt(), 0);
+ QCOMPARE(spy.value(0).value(2).toInt(), rowCount - 1);
+
+ // If the driver doesn't return the query size fetchMore() causes the
+ // model to grow and new signals are emitted
+ if (!db.driver()->hasFeature(QSqlDriver::QuerySize)) {
+ spy.clear();
+ model.fetchMore();
+ int newRowCount = model.rowCount();
+ QCOMPARE(spy.value(0).value(1).toInt(), rowCount);
+ QCOMPARE(spy.value(0).value(2).toInt(), newRowCount - 1);
+ }
+}
+
+// For task 149491: When used with QSortFilterProxyModel, a view and a
+// database that doesn't support the QuerySize feature, blank rows was
+// appended if the query returned more than 256 rows and setQuery()
+// was called more than once. This because an insertion of rows was
+// triggered at the same time as the model was being cleared.
+void tst_QSqlQueryModel::withSortFilterProxyModel()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ if (db.driver()->hasFeature(QSqlDriver::QuerySize))
+ QSKIP("Test applies only for drivers not reporting the query size.", SkipSingle);
+
+ QSqlQueryModel model;
+ model.setQuery(QSqlQuery("SELECT * FROM " + qTableName("test3", __FILE__), db));
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+
+ QTableView view;
+ view.setModel(&proxy);
+
+ QSignalSpy modelRowsRemovedSpy(&model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)));
+ QSignalSpy modelRowsInsertedSpy(&model, SIGNAL(rowsInserted(const QModelIndex &, int, int)));
+ model.setQuery(QSqlQuery("SELECT * FROM " + qTableName("test3", __FILE__), db));
+ view.scrollToBottom();
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ QCOMPARE(proxy.rowCount(), 511);
+
+ // The second call to setQuery() clears the model by removing it's rows.
+ // Only 256 rows because that is what was cached.
+ QCOMPARE(modelRowsRemovedSpy.count(), 1);
+ QCOMPARE(modelRowsRemovedSpy.value(0).value(1).toInt(), 0);
+ QCOMPARE(modelRowsRemovedSpy.value(0).value(2).toInt(), 255);
+
+ // The call to scrollToBottom() forces the model to fetch all rows,
+ // which will be done in two steps.
+ QCOMPARE(modelRowsInsertedSpy.count(), 2);
+ QCOMPARE(modelRowsInsertedSpy.value(0).value(1).toInt(), 0);
+ QCOMPARE(modelRowsInsertedSpy.value(0).value(2).toInt(), 255);
+ QCOMPARE(modelRowsInsertedSpy.value(1).value(1).toInt(), 256);
+ QCOMPARE(modelRowsInsertedSpy.value(1).value(2).toInt(), 510);
+}
+
+// For task 155402: When the model is already empty when setQuery() is called
+// no rows have to be removed and rowsAboutToBeRemoved and rowsRemoved should
+// not be emitted.
+void tst_QSqlQueryModel::setQuerySignalEmission()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlQueryModel model;
+ QSignalSpy modelRowsAboutToBeRemovedSpy(&model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)));
+ QSignalSpy modelRowsRemovedSpy(&model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)));
+
+ // First select, the model was empty and no rows had to be removed!
+ model.setQuery(QSqlQuery("SELECT * FROM " + qTableName("test", __FILE__), db));
+ QCOMPARE(modelRowsAboutToBeRemovedSpy.count(), 0);
+ QCOMPARE(modelRowsRemovedSpy.count(), 0);
+
+ // Second select, the model wasn't empty and two rows had to be removed!
+ model.setQuery(QSqlQuery("SELECT * FROM " + qTableName("test", __FILE__), db));
+ QCOMPARE(modelRowsAboutToBeRemovedSpy.count(), 1);
+ QCOMPARE(modelRowsAboutToBeRemovedSpy.value(0).value(1).toInt(), 0);
+ QCOMPARE(modelRowsAboutToBeRemovedSpy.value(0).value(2).toInt(), 1);
+ QCOMPARE(modelRowsRemovedSpy.count(), 1);
+ QCOMPARE(modelRowsRemovedSpy.value(0).value(1).toInt(), 0);
+ QCOMPARE(modelRowsRemovedSpy.value(0).value(2).toInt(), 1);
+}
+
+// For task 170783: When the query's result set is empty no rows should be inserted,
+// i.e. no rowsAboutToBeInserted or rowsInserted signals should be emitted.
+void tst_QSqlQueryModel::setQueryWithNoRowsInResultSet()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlQueryModel model;
+ QSignalSpy modelRowsAboutToBeInsertedSpy(&model, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)));
+ QSignalSpy modelRowsInsertedSpy(&model, SIGNAL(rowsInserted(const QModelIndex &, int, int)));
+
+ // The query's result set will be empty so no signals should be emitted!
+ QSqlQuery query(db);
+ QVERIFY_SQL(query, exec("SELECT * FROM " + qTableName("test", __FILE__) + " where 0 = 1"));
+ model.setQuery(query);
+ QCOMPARE(modelRowsAboutToBeInsertedSpy.count(), 0);
+ QCOMPARE(modelRowsInsertedSpy.count(), 0);
+}
+
+// For task 180617
+// According to the task, several specific duplicate SQL queries would cause
+// multiple empty grid lines to be visible in the view
+void tst_QSqlQueryModel::task_180617()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ const QString test3(qTableName("test3", __FILE__));
+
+ QTableView view;
+ QCOMPARE(view.columnAt(0), -1);
+ QCOMPARE(view.rowAt(0), -1);
+
+ QSqlQueryModel model;
+ model.setQuery( "SELECT TOP 0 * FROM " + test3, db );
+ view.setModel(&model);
+
+ bool error = false;
+ // Usually a syntax error
+ if (model.lastError().isValid()) // usually a syntax error
+ error = true;
+
+ QCOMPARE(view.columnAt(0), (error)?-1:0 );
+ QCOMPARE(view.rowAt(0), -1);
+
+ model.setQuery( "SELECT TOP 0 * FROM " + test3, db );
+ model.setQuery( "SELECT TOP 0 * FROM " + test3, db );
+ model.setQuery( "SELECT TOP 0 * FROM " + test3, db );
+ model.setQuery( "SELECT TOP 0 * FROM " + test3, db );
+
+ QCOMPARE(view.columnAt(0), (error)?-1:0 );
+ QCOMPARE(view.rowAt(0), -1);
+}
+
+void tst_QSqlQueryModel::task_QTBUG_4963_setHeaderDataWithProxyModel()
+{
+ QSqlQueryModel plainModel;
+ QSortFilterProxyModel proxyModel;
+ proxyModel.setSourceModel(&plainModel);
+ QVERIFY(!plainModel.setHeaderData(0, Qt::Horizontal, QObject::tr("ID")));
+ // And it should not crash.
+}
+
+QTEST_MAIN(tst_QSqlQueryModel)
+#include "tst_qsqlquerymodel.moc"
diff --git a/tests/auto/sql/models/qsqlrelationaltablemodel/.gitignore b/tests/auto/sql/models/qsqlrelationaltablemodel/.gitignore
new file mode 100644
index 0000000000..b6f469c4dc
--- /dev/null
+++ b/tests/auto/sql/models/qsqlrelationaltablemodel/.gitignore
@@ -0,0 +1 @@
+tst_qsqlrelationaltablemodel
diff --git a/tests/auto/sql/models/qsqlrelationaltablemodel/qsqlrelationaltablemodel.pro b/tests/auto/sql/models/qsqlrelationaltablemodel/qsqlrelationaltablemodel.pro
new file mode 100644
index 0000000000..dad42d512c
--- /dev/null
+++ b/tests/auto/sql/models/qsqlrelationaltablemodel/qsqlrelationaltablemodel.pro
@@ -0,0 +1,25 @@
+load(qttest_p4)
+SOURCES += tst_qsqlrelationaltablemodel.cpp
+
+QT += sql
+
+wince*: {
+ plugFiles.files = ../../../plugins/sqldrivers
+ plugFiles.path = .
+ DEPLOYMENT += plugFiles
+ LIBS += -lws2
+}else:symbian {
+ qt_not_deployed {
+ contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2)|contains(S60_VERSION, 5.0) {
+ sqlite.path = /sys/bin
+ sqlite.files = sqlite3.dll
+ DEPLOYMENT += sqlite
+ }
+ }
+} else {
+ win32-g++* {
+ LIBS += -lws2_32
+ } else:win32 {
+ LIBS += ws2_32.lib
+ }
+}
diff --git a/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp b/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp
new file mode 100644
index 0000000000..2c5af13c0c
--- /dev/null
+++ b/tests/auto/sql/models/qsqlrelationaltablemodel/tst_qsqlrelationaltablemodel.cpp
@@ -0,0 +1,1494 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtSql/QtSql>
+
+#include "../../kernel/qsqldatabase/tst_databases.h"
+
+const QString reltest1(qTableName("reltest1", __FILE__)),
+ reltest2(qTableName("reltest2", __FILE__)),
+ reltest3(qTableName("reltest3", __FILE__)),
+ reltest4(qTableName("reltest4", __FILE__)),
+ reltest5(qTableName("reltest5", __FILE__));
+
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QSqlRelationalTableModel : public QObject
+{
+ Q_OBJECT
+
+public:
+ void recreateTestTables(QSqlDatabase);
+
+ tst_Databases dbs;
+
+public slots:
+ void initTestCase_data();
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void data();
+ void setData();
+ void multipleRelation();
+ void insertRecord();
+ void setRecord();
+ void insertWithStrategies();
+ void removeColumn();
+ void filter();
+ void sort();
+ void revert();
+
+ void clearDisplayValuesCache();
+ void insertRecordDuplicateFieldNames();
+ void invalidData();
+ void relationModel();
+ void casing();
+ void escapedRelations();
+ void escapedTableName();
+ void whiteSpaceInIdentifiers();
+ void psqlSchemaTest();
+ void selectAfterUpdate();
+
+private:
+ void dropTestTables( QSqlDatabase db );
+};
+
+
+void tst_QSqlRelationalTableModel::initTestCase_data()
+{
+ dbs.open();
+ if (dbs.fillTestTable() == 0) {
+ qWarning("NO DATABASES");
+ QSKIP("No database drivers are available in this Qt configuration", SkipAll);
+ }
+}
+
+void tst_QSqlRelationalTableModel::recreateTestTables(QSqlDatabase db)
+{
+ dropTestTables(db);
+
+ QSqlQuery q(db);
+ QVERIFY_SQL( q, exec("create table " + reltest1 +
+ " (id int not null primary key, name varchar(20), title_key int, another_title_key int)"));
+ QVERIFY_SQL( q, exec("insert into " + reltest1 + " values(1, 'harry', 1, 2)"));
+ QVERIFY_SQL( q, exec("insert into " + reltest1 + " values(2, 'trond', 2, 1)"));
+ QVERIFY_SQL( q, exec("insert into " + reltest1 + " values(3, 'vohi', 1, 2)"));
+ QVERIFY_SQL( q, exec("insert into " + reltest1 + " values(4, 'boris', 2, 2)"));
+ QVERIFY_SQL( q, exec("insert into " + reltest1 + " values(5, 'nat', NULL, NULL)"));
+ QVERIFY_SQL( q, exec("insert into " + reltest1 + " values(6, 'ale', NULL, 2)"));
+
+ QVERIFY_SQL( q, exec("create table " + reltest2 + " (tid int not null primary key, title varchar(20))"));
+ QVERIFY_SQL( q, exec("insert into " + reltest2 + " values(1, 'herr')"));
+ QVERIFY_SQL( q, exec("insert into " + reltest2 + " values(2, 'mister')"));
+
+ QVERIFY_SQL( q, exec("create table " + reltest3 + " (id int not null primary key, name varchar(20), city_key int)"));
+ QVERIFY_SQL( q, exec("insert into " + reltest3 + " values(1, 'Gustav', 1)"));
+ QVERIFY_SQL( q, exec("insert into " + reltest3 + " values(2, 'Heidi', 2)"));
+
+ QVERIFY_SQL( q, exec("create table " + reltest4 + " (id int not null primary key, name varchar(20))"));
+ QVERIFY_SQL( q, exec("insert into " + reltest4 + " values(1, 'Oslo')"));
+ QVERIFY_SQL( q, exec("insert into " + reltest4 + " values(2, 'Trondheim')"));
+
+ QVERIFY_SQL( q, exec("create table " + reltest5 + " (title varchar(20) not null primary key, abbrev varchar(20))"));
+ QVERIFY_SQL( q, exec("insert into " + reltest5 + " values('herr', 'Hr')"));
+ QVERIFY_SQL( q, exec("insert into " + reltest5 + " values('mister', 'Mr')"));
+
+ if (testWhiteSpaceNames(db.driverName())) {
+ QString reltest6 = db.driver()->escapeIdentifier(qTableName("rel", __FILE__)+" test6", QSqlDriver::TableName);
+ QVERIFY_SQL( q, exec("create table " + reltest6 + " (id int not null primary key, " + db.driver()->escapeIdentifier("city key", QSqlDriver::FieldName) +
+ " int, " + db.driver()->escapeIdentifier("extra field", QSqlDriver::FieldName) + " int)"));
+ QVERIFY_SQL( q, exec("insert into " + reltest6 + " values(1, 1,9)"));
+ QVERIFY_SQL( q, exec("insert into " + reltest6 + " values(2, 2,8)"));
+
+ QString reltest7 = db.driver()->escapeIdentifier(qTableName("rel", __FILE__)+" test7", QSqlDriver::TableName);
+ QVERIFY_SQL( q, exec("create table " + reltest7 + " (" + db.driver()->escapeIdentifier("city id", QSqlDriver::TableName) + " int not null primary key, " + db.driver()->escapeIdentifier("city name", QSqlDriver::FieldName) + " varchar(20))"));
+ QVERIFY_SQL( q, exec("insert into " + reltest7 + " values(1, 'New York')"));
+ QVERIFY_SQL( q, exec("insert into " + reltest7 + " values(2, 'Washington')"));
+ }
+}
+
+void tst_QSqlRelationalTableModel::initTestCase()
+{
+ foreach (const QString &dbname, dbs.dbNames) {
+ QSqlDatabase db=QSqlDatabase::database(dbname);
+ if (db.driverName().startsWith("QIBASE"))
+ db.exec("SET DIALECT 3");
+ else if (tst_Databases::isSqlServer(db)) {
+ db.exec("SET ANSI_DEFAULTS ON");
+ db.exec("SET IMPLICIT_TRANSACTIONS OFF");
+ }
+ else if(tst_Databases::isPostgreSQL(db))
+ db.exec("set client_min_messages='warning'");
+ recreateTestTables(db);
+ }
+}
+
+void tst_QSqlRelationalTableModel::cleanupTestCase()
+{
+ foreach (const QString &dbName, dbs.dbNames) {
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE( db );
+ dropTestTables( QSqlDatabase::database(dbName) );
+ }
+ dbs.close();
+}
+
+void tst_QSqlRelationalTableModel::dropTestTables( QSqlDatabase db )
+{
+ QStringList tableNames;
+ tableNames << reltest1
+ << reltest2
+ << reltest3
+ << reltest4
+ << reltest5
+ << (qTableName( "rel", __FILE__)+" test6")
+ << (qTableName( "rel", __FILE__)+" test7")
+ << qTableName("CASETEST1", db.driver() )
+ << qTableName("casetest1", db.driver() );
+ tst_Databases::safeDropTables( db, tableNames );
+
+ db.exec("DROP SCHEMA "+qTableName("QTBUG_5373", __FILE__)+" CASCADE");
+ db.exec("DROP SCHEMA "+qTableName("QTBUG_5373_s2", __FILE__)+" CASCADE");
+}
+
+void tst_QSqlRelationalTableModel::init()
+{
+}
+
+void tst_QSqlRelationalTableModel::cleanup()
+{
+}
+
+void tst_QSqlRelationalTableModel::data()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlRelationalTableModel model(0, db);
+
+ model.setTable(reltest1);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.columnCount(), 4);
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+
+ //try a non-existent index
+ QVERIFY2(model.data(model.index(0,4)).isValid() == false,"Invalid index returned valid QVariant");
+
+ // check row with null relation: they are reported only in LeftJoin mode
+ QCOMPARE(model.rowCount(), 4);
+
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(4, 0)).toInt(), 5);
+ QCOMPARE(model.data(model.index(4, 1)).toString(), QString("nat"));
+ QVERIFY2(model.data(model.index(4, 2)).isValid() == true, "NULL relation reported with invalid QVariant");
+
+ //check data retrieval when relational key is a non-integer type
+ //in this case a string
+ QSqlRelationalTableModel model2(0,db);
+ model2.setTable(reltest2);
+ model2.setRelation(1, QSqlRelation(reltest5,"title","abbrev"));
+ QVERIFY_SQL(model2, select());
+
+ QCOMPARE(model2.data(model2.index(0, 1)).toString(), QString("Hr"));
+ QCOMPARE(model2.data(model2.index(1, 1)).toString(), QString("Mr"));
+}
+
+void tst_QSqlRelationalTableModel::setData()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ // set the values using OnRowChange Strategy
+ {
+ QSqlRelationalTableModel model(0, db);
+
+ model.setTable(reltest1);
+ model.setSort(0, Qt::AscendingOrder);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ QVERIFY_SQL(model, select());
+
+ QVERIFY(model.setData(model.index(0, 1), QString("harry2")));
+ QVERIFY(model.setData(model.index(0, 2), 2));
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry2"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("mister"));
+
+ model.submit();
+
+ QVERIFY(model.setData(model.index(3,1), QString("boris2")));
+ QVERIFY(model.setData(model.index(3, 2), 1));
+
+ QCOMPARE(model.data(model.index(3,1)).toString(), QString("boris2"));
+ QCOMPARE(model.data(model.index(3, 2)).toString(), QString("herr"));
+
+ model.submit();
+ }
+ { //verify values
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(reltest1);
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry2"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 2);
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("boris2"));
+ QCOMPARE(model.data(model.index(3, 2)).toInt(), 1);
+
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("mister"));
+ QCOMPARE(model.data(model.index(3,2)).toString(), QString("herr"));
+
+ }
+
+ //set the values using OnFieldChange strategy
+ {
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(reltest1);
+ model.setEditStrategy(QSqlTableModel::OnFieldChange);
+ model.setSort(0, Qt::AscendingOrder);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ QVERIFY_SQL(model, select());
+
+ QVERIFY(model.setData(model.index(1,1), QString("trond2")));
+ QVERIFY(model.setData(model.index(2,2), 2));
+
+ QCOMPARE(model.data(model.index(1,1)).toString(), QString("trond2"));
+ QCOMPARE(model.data(model.index(2,2)).toString(), QString("mister"));
+ }
+ { //verify values
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(reltest1);
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond2"));
+ QCOMPARE(model.data(model.index(2, 2)).toInt(), 2);
+
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.data(model.index(2, 2)).toString(), QString("mister"));
+ }
+
+ //set values using OnManualSubmit strategy
+ {
+ QSqlRelationalTableModel model(0, db);
+
+ model.setTable(reltest1);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+
+ //sybase doesn't allow tables with the same alias used twice as col names
+ //so don't set up an identical relation when using the tds driver
+ if (!db.driverName().startsWith("QTDS"))
+ model.setRelation(3, QSqlRelation(reltest2, "tid", "title"));
+
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QVERIFY(model.setData(model.index(2, 1), QString("vohi2")));
+ QVERIFY(model.setData(model.index(3, 2), 1));
+ QVERIFY(model.setData(model.index(0, 3), 1));
+
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi2"));
+ QCOMPARE(model.data(model.index(3, 2)).toString(), QString("herr"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(0, 3)).toString(), QString("herr"));
+ else
+ QCOMPARE(model.data(model.index(0, 3)).toInt(), 1);
+
+ QVERIFY_SQL(model, submitAll());
+ }
+ { //verify values
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(reltest1);
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi2"));
+ QCOMPARE(model.data(model.index(3, 2)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 3)).toInt(), 1);
+
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ if (!db.driverName().startsWith("QTDS"))
+ model.setRelation(3, QSqlRelation(reltest2, "tid", "title"));
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.data(model.index(3, 2)).toString(), QString("herr"));
+
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(0, 3)).toString(), QString("herr"));
+ else
+ QCOMPARE(model.data(model.index(0, 3)).toInt(), 1);
+ }
+
+ //check setting of data when the relational key is a non-integer type
+ //in this case a string.
+ {
+ QSqlRelationalTableModel model(0, db);
+
+ model.setTable(reltest2);
+ model.setRelation(1, QSqlRelation(reltest5, "title", "abbrev"));
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0,1)).toString(), QString("Hr"));
+ QVERIFY(model.setData(model.index(0,1), QString("mister")));
+ QCOMPARE(model.data(model.index(0,1)).toString(), QString("Mr"));
+ QVERIFY_SQL(model, submitAll());
+
+ QCOMPARE(model.data(model.index(0,1)).toString(), QString("Mr"));
+ }
+
+ // Redo same tests, with a LeftJoin
+ {
+ QSqlRelationalTableModel model(0, db);
+
+ model.setTable(reltest2);
+ model.setRelation(1, QSqlRelation(reltest5, "title", "abbrev"));
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0,1)).toString(), QString("Mr"));
+ QVERIFY(model.setData(model.index(0,1), QString("herr")));
+ QCOMPARE(model.data(model.index(0,1)).toString(), QString("Hr"));
+ QVERIFY_SQL(model, submitAll());
+
+ QCOMPARE(model.data(model.index(0,1)).toString(), QString("Hr"));
+ }
+
+}
+
+void tst_QSqlRelationalTableModel::multipleRelation()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ recreateTestTables(db);
+
+ QSqlRelationalTableModel model(0, db);
+
+ model.setTable(reltest1);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ model.setRelation(3, QSqlRelation(reltest4, "id", "name"));
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(2, 0)).toInt(), 3);
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+ QCOMPARE(model.data(model.index(0, 3)).toString(), QString("Trondheim"));
+
+ // Redo same test in the LeftJoin mode
+ model.setTable(reltest1);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ model.setRelation(3, QSqlRelation(reltest4, "id", "name"));
+ model.setSort(0, Qt::AscendingOrder);
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(2, 0)).toInt(), 3);
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+ QCOMPARE(model.data(model.index(0, 3)).toString(), QString("Trondheim"));
+}
+
+void tst_QSqlRelationalTableModel::insertRecord()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlRelationalTableModel model(0, db);
+
+ model.setTable(reltest1);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QSqlRecord rec;
+ QSqlField f1("id", QVariant::Int);
+ QSqlField f2("name", QVariant::String);
+ QSqlField f3("title_key", QVariant::Int);
+ QSqlField f4("another_title_key", QVariant::Int);
+
+ f1.setValue(7);
+ f2.setValue("test");
+ f3.setValue(1);
+ f4.setValue(2);
+
+ f1.setGenerated(true);
+ f2.setGenerated(true);
+ f3.setGenerated(true);
+ f4.setGenerated(true);
+
+ rec.append(f1);
+ rec.append(f2);
+ rec.append(f3);
+ rec.append(f4);
+
+ QVERIFY_SQL(model, insertRecord(-1, rec));
+
+ QCOMPARE(model.data(model.index(4, 0)).toInt(), 7);
+ QCOMPARE(model.data(model.index(4, 1)).toString(), QString("test"));
+ QCOMPARE(model.data(model.index(4, 2)).toString(), QString("herr"));
+
+ // In LeftJoin mode, two additional rows are fetched
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(6, 0)).toInt(), 7);
+ QCOMPARE(model.data(model.index(6, 1)).toString(), QString("test"));
+ QCOMPARE(model.data(model.index(6, 2)).toString(), QString("herr"));
+}
+
+void tst_QSqlRelationalTableModel::setRecord()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ recreateTestTables(db);
+
+ QSqlRelationalTableModel model(0, db);
+
+ model.setTable(reltest1);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QSqlRecord rec;
+ QSqlField f1("id", QVariant::Int);
+ QSqlField f2("name", QVariant::String);
+ QSqlField f3("title_key", QVariant::Int);
+ QSqlField f4("another_title_key", QVariant::Int);
+
+ f1.setValue(7);
+ f2.setValue("tester");
+ f3.setValue(1);
+ f4.setValue(2);
+
+ f1.setGenerated(true);
+ f2.setGenerated(true);
+ f3.setGenerated(true);
+ f4.setGenerated(true);
+
+ rec.append(f1);
+ rec.append(f2);
+ rec.append(f3);
+ rec.append(f4);
+
+ QCOMPARE(model.data(model.index(1, 0)).toInt(), 2);
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(1, 2)).toString(), QString("mister"));
+
+ QVERIFY_SQL(model, setRecord(1, rec));
+
+ QCOMPARE(model.data(model.index(1, 0)).toInt(), 7);
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("tester"));
+ QCOMPARE(model.data(model.index(1, 2)).toString(), QString("herr"));
+
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, submit());
+
+ QCOMPARE(model.data(model.index(3, 0)).toInt(), 7);
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("tester"));
+ QCOMPARE(model.data(model.index(3, 2)).toString(), QString("herr"));
+
+}
+
+void tst_QSqlRelationalTableModel::insertWithStrategies()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlRelationalTableModel model(0, db);
+
+ model.setTable(reltest1);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ model.setSort(0, Qt::AscendingOrder);
+
+ if (!db.driverName().startsWith("QTDS"))
+ model.setRelation(3, QSqlRelation(reltest2, "tid", "title"));
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0,0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0,1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0,2)).toString(), QString("herr"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(0,3)).toString(), QString("mister"));
+ else
+ QCOMPARE(model.data(model.index(0,3)).toInt(), 2);
+
+ model.insertRows(0, 1);
+ model.setData(model.index(0, 0), 1011);
+ model.setData(model.index(0, 1), "test");
+ model.setData(model.index(0, 2), 2);
+ model.setData(model.index(0, 3), 1);
+
+ QCOMPARE(model.data(model.index(0,0)).toInt(), 1011);
+ QCOMPARE(model.data(model.index(0,1)).toString(), QString("test"));
+ QCOMPARE(model.data(model.index(0,2)).toString(), QString("mister"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(0,3)).toString(), QString("herr"));
+ else
+ QCOMPARE(model.data(model.index(0,3)).toInt(), 1);
+
+ QCOMPARE(model.data(model.index(1,0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(1,1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1,2)).toString(), QString("herr"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(1,3)).toString(), QString("mister"));
+ else
+ QCOMPARE(model.data(model.index(1,3)).toInt(), 2);
+
+
+
+ QVERIFY_SQL(model, submitAll());
+
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+
+ QCOMPARE(model.data(model.index(0,0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0,1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0,2)).toString(), QString("herr"));
+
+ if (!db.driverName().startsWith("QTDS")) {
+ QCOMPARE(model.data(model.index(0,3)).toString(), QString("mister"));
+ model.setData(model.index(0,3),1);
+ QCOMPARE(model.data(model.index(0,3)).toString(), QString("herr"));
+ } else {
+ QCOMPARE(model.data(model.index(0,3)).toInt(), 2);
+ model.setData(model.index(0,3),1);
+ QCOMPARE(model.data(model.index(0,3)).toInt(), 1);
+ }
+
+ model.insertRows(0, 2);
+ model.setData(model.index(0, 0), 1012);
+ model.setData(model.index(0, 1), "george");
+ model.setData(model.index(0, 2), 2);
+ model.setData(model.index(0, 3), 2);
+
+ model.setData(model.index(1, 0), 1013);
+ model.setData(model.index(1, 1), "kramer");
+ model.setData(model.index(1, 2), 2);
+ model.setData(model.index(1, 3), 1);
+
+ QCOMPARE(model.data(model.index(0,0)).toInt(),1012);
+ QCOMPARE(model.data(model.index(0,1)).toString(), QString("george"));
+ QCOMPARE(model.data(model.index(0,2)).toString(), QString("mister"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(0,3)).toString(), QString("mister"));
+ else
+ QCOMPARE(model.data(model.index(0,3)).toInt(), 2);
+
+
+ QCOMPARE(model.data(model.index(1,0)).toInt(),1013);
+ QCOMPARE(model.data(model.index(1,1)).toString(), QString("kramer"));
+ QCOMPARE(model.data(model.index(1,2)).toString(), QString("mister"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(1,3)).toString(), QString("herr"));
+ else
+ QCOMPARE(model.data(model.index(1,3)).toInt(), 1);
+
+ QCOMPARE(model.data(model.index(2,0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(2,1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(2,2)).toString(), QString("herr"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(2,3)).toString(), QString("herr"));
+ else
+ QCOMPARE(model.data(model.index(2,3)).toInt(), 1);
+
+ QVERIFY_SQL(model, submitAll());
+}
+
+void tst_QSqlRelationalTableModel::removeColumn()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ recreateTestTables(db);
+
+ QSqlRelationalTableModel model(0, db);
+
+ model.setTable(reltest1);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ QVERIFY_SQL(model, select());
+
+ QVERIFY_SQL(model, removeColumn(3));
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.columnCount(), 3);
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+ QCOMPARE(model.data(model.index(0, 3)), QVariant());
+
+ // try removing more than one column
+ QVERIFY_SQL(model, removeColumns(1, 2));
+ QCOMPARE(model.columnCount(), 1);
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)), QVariant());
+
+ // try in LeftJoin mode the same tests
+ CHECK_DATABASE(db);
+ recreateTestTables(db);
+
+ QSqlRelationalTableModel lmodel(0, db);
+
+ lmodel.setTable(reltest1);
+ lmodel.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ lmodel.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(lmodel, select());
+
+ QVERIFY_SQL(lmodel, removeColumn(3));
+ QVERIFY_SQL(lmodel, select());
+
+ QCOMPARE(lmodel.columnCount(), 3);
+
+ QCOMPARE(lmodel.data(lmodel.index(0, 0)).toInt(), 1);
+ QCOMPARE(lmodel.data(lmodel.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(lmodel.data(lmodel.index(0, 2)).toString(), QString("herr"));
+ QCOMPARE(lmodel.data(lmodel.index(0, 3)), QVariant());
+
+ // try removing more than one column
+ QVERIFY_SQL(lmodel, removeColumns(1, 2));
+ QCOMPARE(lmodel.columnCount(), 1);
+ QCOMPARE(lmodel.data(lmodel.index(0, 0)).toInt(), 1);
+ QCOMPARE(lmodel.data(lmodel.index(0, 1)), QVariant());
+}
+
+void tst_QSqlRelationalTableModel::filter()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ recreateTestTables(db);
+
+ QSqlRelationalTableModel model(0, db);
+
+ model.setTable(reltest1);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ model.setFilter("title = 'herr'");
+
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.rowCount(), 2);
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+ QCOMPARE(model.data(model.index(1, 2)).toString(), QString("herr"));
+
+ // Redo same filter test in LeftJoin mode
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model,select());
+
+ QCOMPARE(model.rowCount(), 2);
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+ QCOMPARE(model.data(model.index(1, 2)).toString(), QString("herr"));
+}
+
+void tst_QSqlRelationalTableModel::sort()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlRelationalTableModel model(0, db);
+
+ model.setTable(reltest1);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ if (!db.driverName().startsWith("QTDS"))
+ model.setRelation(3, QSqlRelation(reltest2, "tid", "title"));
+
+ model.setSort(2, Qt::DescendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.rowCount(), 4);
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("mister"));
+ QCOMPARE(model.data(model.index(1, 2)).toString(), QString("mister"));
+ QCOMPARE(model.data(model.index(2, 2)).toString(), QString("herr"));
+ QCOMPARE(model.data(model.index(3, 2)).toString(), QString("herr"));
+
+
+ model.setSort(3, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ if (!db.driverName().startsWith("QTDS")) {
+ QCOMPARE(model.rowCount(), 4);
+ QCOMPARE(model.data(model.index(0, 3)).toString(), QString("herr"));
+ QCOMPARE(model.data(model.index(1, 3)).toString(), QString("mister"));
+ QCOMPARE(model.data(model.index(2, 3)).toString(), QString("mister"));
+ QCOMPARE(model.data(model.index(3, 3)).toString(), QString("mister"));
+ } else {
+ QCOMPARE(model.data(model.index(0, 3)).toInt(), 1);
+ QCOMPARE(model.data(model.index(1, 3)).toInt(), 2);
+ QCOMPARE(model.data(model.index(2, 3)).toInt(), 2);
+ QCOMPARE(model.data(model.index(3, 3)).toInt(), 2);
+ }
+
+ // redo same test in LeftJoin mode
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ model.setSort(2, Qt::DescendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.rowCount(), 6);
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("mister"));
+ QCOMPARE(model.data(model.index(1, 2)).toString(), QString("mister"));
+ QCOMPARE(model.data(model.index(2, 2)).toString(), QString("herr"));
+ QCOMPARE(model.data(model.index(3, 2)).toString(), QString("herr"));
+ QCOMPARE(model.data(model.index(4, 2)).toString(), QString(""));
+ QCOMPARE(model.data(model.index(5, 2)).toString(), QString(""));
+
+ model.setSort(3, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ if (!db.driverName().startsWith("QTDS")) {
+ QCOMPARE(model.rowCount(), 6);
+ QCOMPARE(model.data(model.index(0, 3)).toString(), QString(""));
+ QCOMPARE(model.data(model.index(1, 3)).toString(), QString("herr"));
+ QCOMPARE(model.data(model.index(2, 3)).toString(), QString("mister"));
+ QCOMPARE(model.data(model.index(3, 3)).toString(), QString("mister"));
+ QCOMPARE(model.data(model.index(4, 3)).toString(), QString("mister"));
+ QCOMPARE(model.data(model.index(5, 3)).toString(), QString("mister"));
+ } else {
+ QCOMPARE(model.data(model.index(0, 3)).toInt(), 1);
+ QCOMPARE(model.data(model.index(1, 3)).toInt(), 2);
+ QCOMPARE(model.data(model.index(2, 3)).toInt(), 2);
+ QCOMPARE(model.data(model.index(3, 3)).toInt(), 2);
+ }
+}
+
+static void testRevert(QSqlRelationalTableModel &model)
+{
+ /* revert single row */
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+ QVERIFY(model.setData(model.index(0, 2), 2, Qt::EditRole));
+
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("mister"));
+ model.revertRow(0);
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+
+ /* revert all */
+ QVERIFY(model.setData(model.index(0, 2), 2, Qt::EditRole));
+
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("mister"));
+ model.revertAll();
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+
+ // the following only works for OnManualSubmit
+ if (model.editStrategy() != QSqlTableModel::OnManualSubmit)
+ return;
+
+ /* revert inserted rows */
+ int initialRowCount = model.rowCount();
+ QVERIFY(model.insertRows(4, 4));
+ QVERIFY(model.rowCount() == (initialRowCount + 4));
+
+ /* make sure the new rows are initialized to nothing */
+ QVERIFY(model.data(model.index(4, 2)).toString().isEmpty());
+ QVERIFY(model.data(model.index(5, 2)).toString().isEmpty());
+ QVERIFY(model.data(model.index(6, 2)).toString().isEmpty());
+ QVERIFY(model.data(model.index(7, 2)).toString().isEmpty());
+
+ /* Set some values */
+ QVERIFY(model.setData(model.index(4, 0), 42, Qt::EditRole));
+ QVERIFY(model.setData(model.index(5, 0), 43, Qt::EditRole));
+ QVERIFY(model.setData(model.index(6, 0), 44, Qt::EditRole));
+ QVERIFY(model.setData(model.index(7, 0), 45, Qt::EditRole));
+
+ QVERIFY(model.setData(model.index(4, 2), 2, Qt::EditRole));
+ QVERIFY(model.setData(model.index(5, 2), 2, Qt::EditRole));
+ QVERIFY(model.setData(model.index(6, 2), 1, Qt::EditRole));
+ QVERIFY(model.setData(model.index(7, 2), 2, Qt::EditRole));
+
+ /* Now revert the newly inserted rows */
+ model.revertAll();
+ QVERIFY(model.rowCount() == initialRowCount);
+
+ /* Insert rows again */
+ QVERIFY(model.insertRows(4, 4));
+
+ /* make sure the new rows are initialized to nothing */
+ QVERIFY(model.data(model.index(4, 2)).toString().isEmpty());
+ QVERIFY(model.data(model.index(5, 2)).toString().isEmpty());
+ QVERIFY(model.data(model.index(6, 2)).toString().isEmpty());
+ QVERIFY(model.data(model.index(7, 2)).toString().isEmpty());
+}
+
+void tst_QSqlRelationalTableModel::revert()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlRelationalTableModel model(0, db);
+
+ model.setTable(reltest1);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ model.setRelation(3, QSqlRelation(reltest4, "id", "name"));
+
+ model.setSort(0, Qt::AscendingOrder);
+
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.data(model.index(0, 0)).toString(), QString("1"));
+
+ testRevert(model);
+ if (QTest::currentTestFailed())
+ return;
+
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model, select());
+ testRevert(model);
+
+ /* and again with OnManualSubmit */
+ model.setJoinMode(QSqlRelationalTableModel::InnerJoin);
+ QVERIFY_SQL(model, select());
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ testRevert(model);
+
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model, select());
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ testRevert(model);
+}
+
+void tst_QSqlRelationalTableModel::clearDisplayValuesCache()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlRelationalTableModel model(0, db);
+
+ model.setTable(reltest1);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+
+ if (!db.driverName().startsWith("QTDS"))
+ model.setRelation(3, QSqlRelation(reltest2, "tid", "title"));
+ model.setSort(1, Qt::AscendingOrder);
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(3, 0)).toInt(), 3);
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("vohi"));
+ QCOMPARE(model.data(model.index(3, 2)).toString(), QString("herr"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(3, 3)).toString(), QString("mister"));
+ else
+ QCOMPARE(model.data(model.index(3, 3)).toInt(), 2 );
+
+ model.insertRow(model.rowCount());
+ QVERIFY(model.setData(model.index(4, 0), 7, Qt::EditRole));
+ QVERIFY(model.setData(model.index(4, 1), "anders", Qt::EditRole));
+ QVERIFY(model.setData(model.index(4, 2), 1, Qt::EditRole));
+ QVERIFY(model.setData(model.index(4, 3), 1, Qt::EditRole));
+ model.submitAll();
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 7);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("anders"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(0, 3)).toString(), QString("herr"));
+ else
+ QCOMPARE(model.data(model.index(0, 3)).toInt(), 1);
+
+ QCOMPARE(model.data(model.index(4, 0)).toInt(), 3);
+ QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi"));
+ QCOMPARE(model.data(model.index(4, 2)).toString(), QString("herr"));
+ if (!db.driverName().startsWith("QTDS"))
+ QCOMPARE(model.data(model.index(4, 3)).toString(), QString("mister"));
+ else
+ QCOMPARE(model.data(model.index(4, 3)).toInt(), 2);
+}
+
+// For task 140782 and 176374: If the main table and the the related tables uses the same
+// name for a column or display column then insertRecord() would return true though it
+// actually failed.
+void tst_QSqlRelationalTableModel::insertRecordDuplicateFieldNames()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(reltest3);
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ model.setSort(0, Qt::AscendingOrder);
+
+ // Duplication of "name", used in both reltest3 and reltest4.
+ model.setRelation(2, QSqlRelation(reltest4, "id", "name"));
+ QVERIFY_SQL(model, select());
+
+ if (db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2")) {
+ QCOMPARE(model.record(1).value((reltest4+QLatin1String("_name_2")).toUpper()).toString(),
+ QString("Trondheim"));
+ } else {
+ QCOMPARE(model.record(1).value((reltest4+QLatin1String("_name_2"))).toString(),
+ QString("Trondheim"));
+ }
+
+ QSqlRecord rec = model.record();
+ rec.setValue(0, 3);
+ rec.setValue(1, "Berge");
+ rec.setValue(2, 1); // Must insert the key value
+
+ if (db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2")) {
+ QCOMPARE(rec.fieldName(0), QLatin1String("ID"));
+ QCOMPARE(rec.fieldName(1), QLatin1String("NAME")); // This comes from main table
+ } else {
+ QCOMPARE(rec.fieldName(0), QLatin1String("id"));
+ QCOMPARE(rec.fieldName(1), QLatin1String("name"));
+ }
+
+ // The duplicate field names is aliased because it's comes from the relation's display column.
+ if(db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2"))
+ QCOMPARE(rec.fieldName(2), (reltest4+QLatin1String("_name_2")).toUpper());
+ else
+ QCOMPARE(rec.fieldName(2), reltest4+QLatin1String("_name_2"));
+
+ QVERIFY(model.insertRecord(-1, rec));
+ QCOMPARE(model.data(model.index(2, 2)).toString(), QString("Oslo"));
+ QVERIFY(model.submitAll());
+ QCOMPARE(model.data(model.index(2, 2)).toString(), QString("Oslo"));
+}
+
+void tst_QSqlRelationalTableModel::invalidData()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(reltest1);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ QVERIFY_SQL(model, select());
+
+ //try set a non-existent relational key
+ QVERIFY(model.setData(model.index(0, 2), 3) == false);
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+
+ //try to set data in non valid index
+ QVERIFY(model.setData(model.index(0,10),5) == false);
+
+ //same test with LeftJoin mode
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model, select());
+
+ //try set a non-existent relational key
+ QVERIFY(model.setData(model.index(0, 2), 3) == false);
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+
+ //try to set data in non valid index
+ QVERIFY(model.setData(model.index(0,10),5) == false);
+}
+
+void tst_QSqlRelationalTableModel::relationModel()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(reltest1);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ QVERIFY_SQL(model, select());
+
+ QVERIFY(model.relationModel(0) == NULL);
+ QVERIFY(model.relationModel(1) == NULL);
+ QVERIFY(model.relationModel(2) != NULL);
+ QVERIFY(model.relationModel(3) == NULL);
+ QVERIFY(model.relationModel(4) == NULL);
+
+ model.setRelation(3, QSqlRelation(reltest4, "id", "name"));
+ QVERIFY_SQL(model, select());
+
+ QVERIFY(model.relationModel(0) == NULL);
+ QVERIFY(model.relationModel(1) == NULL);
+ QVERIFY(model.relationModel(2) != NULL);
+ QVERIFY(model.relationModel(3) != NULL);
+ QVERIFY(model.relationModel(4) == NULL);
+
+ QSqlTableModel *rel_model = model.relationModel(2);
+ QCOMPARE(rel_model->data(rel_model->index(0,1)).toString(), QString("herr"));
+
+ //same test in JoinMode
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model, select());
+
+ QVERIFY(model.relationModel(0) == NULL);
+ QVERIFY(model.relationModel(1) == NULL);
+ QVERIFY(model.relationModel(2) != NULL);
+ QVERIFY(model.relationModel(3) != NULL);
+ QVERIFY(model.relationModel(4) == NULL);
+
+ QSqlTableModel *rel_model2 = model.relationModel(2);
+ QCOMPARE(rel_model2->data(rel_model->index(0,1)).toString(), QString("herr"));
+}
+
+void tst_QSqlRelationalTableModel::casing()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ if (db.driverName().startsWith("QSQLITE") || db.driverName().startsWith("QIBASE") || tst_Databases::isSqlServer(db))
+ QSKIP("The casing test for this database is irrelevant since this database does not treat different cases as separate entities", SkipAll);
+
+ QSqlQuery q(db);
+ QVERIFY_SQL( q, exec("create table " + qTableName("CASETEST1", db.driver()).toUpper() +
+ " (id int not null primary key, name varchar(20), title_key int, another_title_key int)"));
+
+ if( !q.exec("create table " + qTableName("casetest1", db.driver()) +
+ " (ident int not null primary key, name varchar(20), title_key int)"))
+ QSKIP("The casing test for this database is irrelevant since this database does not treat different cases as separate entities", SkipAll);
+
+ QVERIFY_SQL( q, exec("insert into " + qTableName("CASETEST1", db.driver()).toUpper() + " values(1, 'harry', 1, 2)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("CASETEST1", db.driver()).toUpper() + " values(2, 'trond', 2, 1)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("CASETEST1", db.driver()).toUpper() + " values(3, 'vohi', 1, 2)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("CASETEST1", db.driver()).toUpper() + " values(4, 'boris', 2, 2)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("casetest1", db.driver()) + " values(1, 'jerry', 1)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("casetest1", db.driver()) + " values(2, 'george', 2)"));
+ QVERIFY_SQL( q, exec("insert into " + qTableName("casetest1", db.driver()) + " values(4, 'kramer', 2)"));
+
+ if (db.driverName().startsWith("QOCI")) {
+ //try an owner that doesn't exist
+ QSqlRecord rec = db.driver()->record("doug." + qTableName("CASETEST1", db.driver()).toUpper());
+ QCOMPARE( rec.count(), 0);
+
+ //try an owner that does exist
+ rec = db.driver()->record(db.userName() + "." + qTableName("CASETEST1", db.driver()).toUpper());
+ QCOMPARE( rec.count(), 4);
+ }
+ QSqlRecord rec = db.driver()->record(qTableName("CASETEST1", db.driver()).toUpper());
+ QCOMPARE( rec.count(), 4);
+
+ rec = db.driver()->record(qTableName("casetest1", db.driver()));
+ QCOMPARE( rec.count(), 3);
+
+ QSqlTableModel upperCaseModel(0, db);
+ upperCaseModel.setTable(qTableName("CASETEST1", db.driver()).toUpper());
+
+ QCOMPARE(upperCaseModel.tableName(),qTableName("CASETEST1",db.driver()).toUpper());
+
+ QVERIFY_SQL(upperCaseModel, select());
+
+ QCOMPARE(upperCaseModel.rowCount(), 4);
+
+ QSqlTableModel lowerCaseModel(0, db);
+ lowerCaseModel.setTable(qTableName("casetest1", db.driver()));
+ QCOMPARE(lowerCaseModel.tableName(), qTableName("casetest1",db.driver()));
+ QVERIFY_SQL(lowerCaseModel, select());
+
+ QCOMPARE(lowerCaseModel.rowCount(), 3);
+
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(qTableName("CASETEST1", db.driver()).toUpper());
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+}
+
+void tst_QSqlRelationalTableModel::escapedRelations()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ recreateTestTables(db);
+
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(reltest1);
+
+ //try with relation table name quoted
+ if (db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2")) {
+ model.setRelation(2, QSqlRelation(db.driver()->escapeIdentifier(reltest2.toUpper(),QSqlDriver::TableName),
+ "tid",
+ "title"));
+ } else {
+ model.setRelation(2, QSqlRelation(db.driver()->escapeIdentifier(reltest2,QSqlDriver::TableName),
+ "tid",
+ "title"));
+
+ }
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+
+ //try with index column quoted
+ model.setJoinMode(QSqlRelationalTableModel::InnerJoin);
+ if (db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2")) {
+ model.setRelation(2, QSqlRelation(reltest2,
+ db.driver()->escapeIdentifier("tid", QSqlDriver::FieldName).toUpper(),
+ "title"));
+ } else {
+ model.setRelation(2, QSqlRelation(reltest2,
+ db.driver()->escapeIdentifier("tid", QSqlDriver::FieldName),
+ "title"));
+ }
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+
+ //try with display column quoted
+ model.setJoinMode(QSqlRelationalTableModel::InnerJoin);
+ if (db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2")) {
+
+ model.setRelation(2, QSqlRelation(reltest2,
+ "tid",
+ db.driver()->escapeIdentifier("title", QSqlDriver::FieldName).toUpper()));
+ } else {
+ model.setRelation(2, QSqlRelation(reltest2,
+ "tid",
+ db.driver()->escapeIdentifier("title", QSqlDriver::FieldName)));
+ }
+
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+
+ //try with tablename and index and display columns quoted in the relation
+ model.setJoinMode(QSqlRelationalTableModel::InnerJoin);
+ if (db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2")) {
+ model.setRelation(2, QSqlRelation(reltest2,
+ "tid",
+ db.driver()->escapeIdentifier("title", QSqlDriver::FieldName).toUpper()));
+ } else {
+ model.setRelation(2, QSqlRelation(reltest2,
+ "tid",
+ db.driver()->escapeIdentifier("title", QSqlDriver::FieldName)));
+ }
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("herr"));
+}
+
+void tst_QSqlRelationalTableModel::escapedTableName()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ // set the values using OnRowChange Strategy with an escaped tablename
+ {
+ QSqlRelationalTableModel model(0, db);
+
+ if (db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2")) {
+ model.setTable(db.driver()->escapeIdentifier(reltest1.toUpper(), QSqlDriver::TableName));
+ } else {
+ model.setTable(db.driver()->escapeIdentifier(reltest1, QSqlDriver::TableName));
+ }
+ model.setSort(0, Qt::AscendingOrder);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ QVERIFY_SQL(model, select());
+
+ QVERIFY(model.setData(model.index(0, 1), QString("harry2")));
+ QVERIFY(model.setData(model.index(0, 2), 2));
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry2"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("mister"));
+
+ model.submit();
+
+ QVERIFY(model.setData(model.index(3,1), QString("boris2")));
+ QVERIFY(model.setData(model.index(3, 2), 1));
+
+ QCOMPARE(model.data(model.index(3,1)).toString(), QString("boris2"));
+ QCOMPARE(model.data(model.index(3, 2)).toString(), QString("herr"));
+
+ model.submit();
+ }
+ { //verify values
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(reltest1);
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry2"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 2);
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("boris2"));
+ QCOMPARE(model.data(model.index(3, 2)).toInt(), 1);
+
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("mister"));
+ QCOMPARE(model.data(model.index(3,2)).toString(), QString("herr"));
+
+ }
+
+ //ok, now do same test with LeftJoin
+ {
+ QSqlRelationalTableModel model(0, db);
+
+ if (db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2")) {
+ model.setTable(db.driver()->escapeIdentifier(reltest1.toUpper(), QSqlDriver::TableName));
+ } else {
+ model.setTable(db.driver()->escapeIdentifier(reltest1, QSqlDriver::TableName));
+ }
+ model.setSort(0, Qt::AscendingOrder);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model, select());
+
+ QVERIFY(model.setData(model.index(0, 1), QString("harry2")));
+ QVERIFY(model.setData(model.index(0, 2), 2));
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry2"));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("mister"));
+
+ model.submit();
+
+ QVERIFY(model.setData(model.index(3,1), QString("boris2")));
+ QVERIFY(model.setData(model.index(3, 2), 1));
+
+ QCOMPARE(model.data(model.index(3,1)).toString(), QString("boris2"));
+ QCOMPARE(model.data(model.index(3, 2)).toString(), QString("herr"));
+
+ model.submit();
+ }
+ { //verify values
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(reltest1);
+ model.setSort(0, Qt::AscendingOrder);
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry2"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 2);
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("boris2"));
+ QCOMPARE(model.data(model.index(3, 2)).toInt(), 1);
+
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("mister"));
+ QCOMPARE(model.data(model.index(3,2)).toString(), QString("herr"));
+
+ }
+}
+
+void tst_QSqlRelationalTableModel::whiteSpaceInIdentifiers()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ if (!testWhiteSpaceNames(db.driverName()))
+ QSKIP("White space test irrelevant for driver", SkipAll);
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(db.driver()->escapeIdentifier(qTableName("rel", __FILE__)+" test6", QSqlDriver::TableName));
+ model.setSort(0, Qt::DescendingOrder);
+ model.setRelation(1, QSqlRelation(db.driver()->escapeIdentifier(qTableName("rel", __FILE__)+" test7", QSqlDriver::TableName),
+ db.driver()->escapeIdentifier("city id", QSqlDriver::FieldName),
+ db.driver()->escapeIdentifier("city name", QSqlDriver::FieldName)));
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0,1)).toString(), QString("Washington"));
+ QCOMPARE(model.data(model.index(1,1)).toString(), QString("New York"));
+
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0,1)).toString(), QString("Washington"));
+ QCOMPARE(model.data(model.index(1,1)).toString(), QString("New York"));
+
+ model.setJoinMode(QSqlRelationalTableModel::InnerJoin);
+ QVERIFY_SQL(model, select());
+
+ QSqlRecord rec;
+ QSqlField f1("id", QVariant::Int);
+ QSqlField f2(db.driver()->escapeIdentifier("city key", QSqlDriver::FieldName), QVariant::Int);
+ QSqlField f3(db.driver()->escapeIdentifier("extra field", QSqlDriver::FieldName), QVariant::Int);
+
+ f1.setValue(3);
+ f2.setValue(2);
+ f3.setValue(7);
+
+ f1.setGenerated(true);
+ f2.setGenerated(true);
+ f3.setGenerated(true);
+
+ rec.append(f1);
+ rec.append(f2);
+ rec.append(f3);
+
+ QVERIFY_SQL(model, insertRecord(-1, rec));
+ model.submitAll();
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 3);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("Washington"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 7);
+
+ //TODO: For some reson setting a record using manual submit fails
+ //model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+
+ QSqlRecord recNew;
+ QSqlField f1New("id", QVariant::Int);
+ QSqlField f2New(db.driver()->escapeIdentifier("city key", QSqlDriver::FieldName), QVariant::Int);
+ QSqlField f3New(db.driver()->escapeIdentifier("extra field", QSqlDriver::FieldName), QVariant::Int);
+
+ f1New.setValue(4);
+ f2New.setValue(1);
+ f3New.setValue(6);
+
+ f1New.setGenerated(true);
+ f2New.setGenerated(true);
+ f3New.setGenerated(true);
+
+ recNew.append(f1New);
+ recNew.append(f2New);
+ recNew.append(f3New);
+
+ QVERIFY_SQL(model, setRecord(0, recNew));
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 4);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("New York"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 6);
+
+ QVERIFY_SQL(model, submitAll());
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 4);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("New York"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 6);
+}
+
+void tst_QSqlRelationalTableModel::psqlSchemaTest()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ if(!tst_Databases::isPostgreSQL(db)) {
+ QSKIP("Postgresql specific test", SkipSingle);
+ return;
+ }
+ QSqlRelationalTableModel model(0, db);
+ QSqlQuery q(db);
+ QVERIFY_SQL(q, exec("create schema "+qTableName("QTBUG_5373", __FILE__)));
+ QVERIFY_SQL(q, exec("create schema "+qTableName("QTBUG_5373_s2", __FILE__)));
+ QVERIFY_SQL(q, exec("create table "+qTableName("QTBUG_5373", __FILE__)+"."+qTableName("document", __FILE__)+"(document_id int primary key, relatingid int, userid int)"));
+ QVERIFY_SQL(q, exec("create table "+qTableName("QTBUG_5373_s2", __FILE__)+"."+qTableName("user", __FILE__)+"(userid int primary key, username char(40))"));
+ model.setTable(qTableName("QTBUG_5373", __FILE__)+"."+qTableName("document", __FILE__));
+ model.setRelation(1, QSqlRelation(qTableName("QTBUG_5373_s2", __FILE__)+"."+qTableName("user", __FILE__), "userid", "username"));
+ model.setRelation(2, QSqlRelation(qTableName("QTBUG_5373_s2", __FILE__)+"."+qTableName("user", __FILE__), "userid", "username"));
+ QVERIFY_SQL(model, select());
+
+ model.setJoinMode(QSqlRelationalTableModel::LeftJoin);
+ QVERIFY_SQL(model, select());
+}
+
+void tst_QSqlRelationalTableModel::selectAfterUpdate()
+{
+ QFETCH_GLOBAL(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlRelationalTableModel model(0, db);
+ model.setTable(reltest1);
+ model.setRelation(2, QSqlRelation(reltest2, "tid", "title"));
+ QVERIFY_SQL(model, select());
+ QVERIFY(model.relationModel(2)->rowCount() == 2);
+ {
+ QSqlQuery q(db);
+ QVERIFY_SQL(q, exec("insert into " + reltest2 + " values(3, 'mrs')"));
+ model.relationModel(2)->select();
+ }
+ QVERIFY(model.relationModel(2)->rowCount() == 3);
+ QVERIFY(model.setData(model.index(0,2), 3));
+ QVERIFY(model.submitAll());
+ QCOMPARE(model.data(model.index(0,2)), QVariant("mrs"));
+}
+
+QTEST_MAIN(tst_QSqlRelationalTableModel)
+#include "tst_qsqlrelationaltablemodel.moc"
diff --git a/tests/auto/sql/models/qsqltablemodel/.gitignore b/tests/auto/sql/models/qsqltablemodel/.gitignore
new file mode 100644
index 0000000000..460982f59c
--- /dev/null
+++ b/tests/auto/sql/models/qsqltablemodel/.gitignore
@@ -0,0 +1 @@
+tst_qsqltablemodel
diff --git a/tests/auto/sql/models/qsqltablemodel/qsqltablemodel.pro b/tests/auto/sql/models/qsqltablemodel/qsqltablemodel.pro
new file mode 100644
index 0000000000..e49020f0a6
--- /dev/null
+++ b/tests/auto/sql/models/qsqltablemodel/qsqltablemodel.pro
@@ -0,0 +1,22 @@
+load(qttest_p4)
+SOURCES += tst_qsqltablemodel.cpp
+
+QT += sql
+
+wince*: {
+ plugFiles.files = ../../../plugins/sqldrivers
+ plugFiles.path = .
+ DEPLOYMENT += plugFiles
+ LIBS += -lws2
+}else:symbian {
+ qt_not_deployed {
+ contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2)|contains(S60_VERSION, 5.0) {
+ sqlite.path = /sys/bin
+ sqlite.files = sqlite3.dll
+ DEPLOYMENT += sqlite
+ }
+ }
+}else {
+ win32:LIBS += -lws2_32
+}
+
diff --git a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
new file mode 100644
index 0000000000..07efd4a3a1
--- /dev/null
+++ b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp
@@ -0,0 +1,1377 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include "../../kernel/qsqldatabase/tst_databases.h"
+#include <QtSql>
+
+const QString test(qTableName("test", __FILE__)),
+ test2(qTableName("test2", __FILE__)),
+ test3(qTableName("test3", __FILE__));
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+Q_DECLARE_METATYPE(QModelIndex)
+
+class tst_QSqlTableModel : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QSqlTableModel();
+ virtual ~tst_QSqlTableModel();
+
+
+ void dropTestTables();
+ void createTestTables();
+ void recreateTestTables();
+ void repopulateTestTables();
+
+ tst_Databases dbs;
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+
+ void select_data() { generic_data(); }
+ void select();
+ void insertColumns_data() { generic_data_with_strategies(); }
+ void insertColumns();
+ void submitAll_data() { generic_data(); }
+ void submitAll();
+ void setRecord_data() { generic_data(); }
+ void setRecord();
+ void insertRow_data() { generic_data_with_strategies(); }
+ void insertRow();
+ void insertRecord_data() { generic_data(); }
+ void insertRecord();
+ void insertMultiRecords_data() { generic_data(); }
+ void insertMultiRecords();
+ void removeRow_data() { generic_data(); }
+ void removeRow();
+ void removeRows_data() { generic_data(); }
+ void removeRows();
+ void removeInsertedRow_data() { generic_data_with_strategies(); }
+ void removeInsertedRow();
+ void removeInsertedRows_data() { generic_data(); }
+ void removeInsertedRows();
+ void setFilter_data() { generic_data(); }
+ void setFilter();
+ void setInvalidFilter_data() { generic_data(); }
+ void setInvalidFilter();
+
+ void emptyTable_data() { generic_data(); }
+ void emptyTable();
+ void tablesAndSchemas_data() { generic_data("QPSQL"); }
+ void tablesAndSchemas();
+ void whitespaceInIdentifiers_data() { generic_data(); }
+ void whitespaceInIdentifiers();
+ void primaryKeyOrder_data() { generic_data("QSQLITE"); }
+ void primaryKeyOrder();
+
+ void sqlite_bigTable_data() { generic_data("QSQLITE"); }
+ void sqlite_bigTable();
+
+ // bug specific tests
+ void insertRecordBeforeSelect_data() { generic_data(); }
+ void insertRecordBeforeSelect();
+ void submitAllOnInvalidTable_data() { generic_data(); }
+ void submitAllOnInvalidTable();
+ void insertRecordsInLoop_data() { generic_data(); }
+ void insertRecordsInLoop();
+ void sqlite_attachedDatabase_data() { generic_data("QSQLITE"); }
+ void sqlite_attachedDatabase(); // For task 130799
+ void tableModifyWithBlank_data() { generic_data(); }
+ void tableModifyWithBlank(); // For mail task
+
+ void removeColumnAndRow_data() { generic_data(); }
+ void removeColumnAndRow(); // task 256032
+
+ void insertBeforeDelete_data() { generic_data(); }
+ void insertBeforeDelete();
+private:
+ void generic_data(const QString& engine=QString());
+ void generic_data_with_strategies(const QString& engine=QString());
+};
+
+tst_QSqlTableModel::tst_QSqlTableModel()
+{
+ qRegisterMetaType<QModelIndex>("QModelIndex");
+ dbs.open();
+}
+
+tst_QSqlTableModel::~tst_QSqlTableModel()
+{
+}
+
+void tst_QSqlTableModel::dropTestTables()
+{
+ for (int i = 0; i < dbs.dbNames.count(); ++i) {
+ QSqlDatabase db = QSqlDatabase::database(dbs.dbNames.at(i));
+ QSqlQuery q(db);
+ if(tst_Databases::isPostgreSQL(db))
+ QVERIFY_SQL( q, exec("set client_min_messages='warning'"));
+
+ QStringList tableNames;
+ tableNames << test
+ << test2
+ << test3
+ << qTableName("test4", __FILE__)
+ << qTableName("emptytable", __FILE__)
+ << qTableName("bigtable", __FILE__)
+ << qTableName("foo", __FILE__);
+ if (testWhiteSpaceNames(db.driverName()))
+ tableNames << qTableName("qtestw hitespace", db.driver());
+
+ tst_Databases::safeDropTables(db, tableNames);
+
+ if (db.driverName().startsWith("QPSQL")) {
+ q.exec("DROP SCHEMA " + qTableName("testschema", __FILE__) + " CASCADE");
+ }
+ }
+}
+
+void tst_QSqlTableModel::createTestTables()
+{
+ for (int i = 0; i < dbs.dbNames.count(); ++i) {
+ QSqlDatabase db = QSqlDatabase::database(dbs.dbNames.at(i));
+ QSqlQuery q(db);
+
+ QVERIFY_SQL( q, exec("create table " + test + "(id int, name varchar(20), title int)"));
+
+ QVERIFY_SQL( q, exec("create table " + test2 + "(id int, title varchar(20))"));
+
+ QVERIFY_SQL( q, exec("create table " + test3 + "(id int, random varchar(20), randomtwo varchar(20))"));
+
+ if(!tst_Databases::isSqlServer(db))
+ QVERIFY_SQL( q, exec("create table " + qTableName("test4", __FILE__) + "(column1 varchar(50), column2 varchar(50), column3 varchar(50))"));
+ else
+ QVERIFY_SQL( q, exec("create table " + qTableName("test4", __FILE__) + "(column1 varchar(50), column2 varchar(50) NULL, column3 varchar(50))"));
+
+
+ QVERIFY_SQL( q, exec("create table " + qTableName("emptytable", __FILE__) + "(id int)"));
+
+ if (testWhiteSpaceNames(db.driverName())) {
+ QString qry = "create table " + qTableName("qtestw hitespace", db.driver()) + " ("+ db.driver()->escapeIdentifier("a field", QSqlDriver::FieldName) + " int)";
+ QVERIFY_SQL( q, exec(qry));
+ }
+ }
+}
+
+void tst_QSqlTableModel::repopulateTestTables()
+{
+ for (int i = 0; i < dbs.dbNames.count(); ++i) {
+ QSqlDatabase db = QSqlDatabase::database(dbs.dbNames.at(i));
+ QSqlQuery q(db);
+
+ q.exec("delete from " + test);
+ QVERIFY_SQL( q, exec("insert into " + test + " values(1, 'harry', 1)"));
+ QVERIFY_SQL( q, exec("insert into " + test + " values(2, 'trond', 2)"));
+ QVERIFY_SQL( q, exec("insert into " + test + " values(3, 'vohi', 3)"));
+
+ q.exec("delete from " + test2);
+ QVERIFY_SQL( q, exec("insert into " + test2 + " values(1, 'herr')"));
+ QVERIFY_SQL( q, exec("insert into " + test2 + " values(2, 'mister')"));
+
+ q.exec("delete from " + test3);
+ QVERIFY_SQL( q, exec("insert into " + test3 + " values(1, 'foo', 'bar')"));
+ QVERIFY_SQL( q, exec("insert into " + test3 + " values(2, 'baz', 'joe')"));
+ }
+}
+
+void tst_QSqlTableModel::recreateTestTables()
+{
+ dropTestTables();
+ createTestTables();
+ repopulateTestTables();
+}
+
+void tst_QSqlTableModel::generic_data(const QString &engine)
+{
+ if ( dbs.fillTestTable(engine) == 0 ) {
+ if (engine.isEmpty())
+ QSKIP( "No database drivers are available in this Qt configuration", SkipAll );
+ else
+ QSKIP( (QString("No database drivers of type %1 are available in this Qt configuration").arg(engine)).toLocal8Bit(), SkipAll );
+ }
+}
+
+void tst_QSqlTableModel::generic_data_with_strategies(const QString &engine)
+{
+ if ( dbs.fillTestTableWithStrategies(engine) == 0 ) {
+ if (engine.isEmpty())
+ QSKIP( "No database drivers are available in this Qt configuration", SkipAll );
+ else
+ QSKIP( (QString("No database drivers of type %1 are available in this Qt configuration").arg(engine)).toLocal8Bit(), SkipAll );
+ }
+}
+
+void tst_QSqlTableModel::initTestCase()
+{
+ recreateTestTables();
+}
+
+void tst_QSqlTableModel::cleanupTestCase()
+{
+ dropTestTables();
+ dbs.close();
+}
+
+void tst_QSqlTableModel::init()
+{
+}
+
+void tst_QSqlTableModel::cleanup()
+{
+ repopulateTestTables();
+}
+
+void tst_QSqlTableModel::select()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ model.setTable(test);
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.rowCount(), 3);
+ QCOMPARE(model.columnCount(), 3);
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 3)), QVariant());
+
+ QCOMPARE(model.data(model.index(1, 0)).toInt(), 2);
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(1, 2)).toInt(), 2);
+ QCOMPARE(model.data(model.index(1, 3)), QVariant());
+
+ QCOMPARE(model.data(model.index(2, 0)).toInt(), 3);
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi"));
+ QCOMPARE(model.data(model.index(2, 2)).toInt(), 3);
+ QCOMPARE(model.data(model.index(2, 3)), QVariant());
+
+ QCOMPARE(model.data(model.index(3, 0)), QVariant());
+ QCOMPARE(model.data(model.index(3, 1)), QVariant());
+ QCOMPARE(model.data(model.index(3, 2)), QVariant());
+ QCOMPARE(model.data(model.index(3, 3)), QVariant());
+}
+
+void tst_QSqlTableModel::insertColumns()
+{
+ // Just like the select test, with extra stuff
+ QFETCH(QString, dbName);
+ QFETCH(int, submitpolicy_i);
+ QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i;
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ model.setTable(test);
+ model.setSort(0, Qt::AscendingOrder);
+ model.setEditStrategy(submitpolicy);
+
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.rowCount(), 3);
+ QCOMPARE(model.columnCount(), 3);
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 3)), QVariant());
+
+ QCOMPARE(model.data(model.index(1, 0)).toInt(), 2);
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(1, 2)).toInt(), 2);
+ QCOMPARE(model.data(model.index(1, 3)), QVariant());
+
+ QCOMPARE(model.data(model.index(2, 0)).toInt(), 3);
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi"));
+ QCOMPARE(model.data(model.index(2, 2)).toInt(), 3);
+ QCOMPARE(model.data(model.index(2, 3)), QVariant());
+
+ QCOMPARE(model.data(model.index(3, 0)), QVariant());
+ QCOMPARE(model.data(model.index(3, 1)), QVariant());
+ QCOMPARE(model.data(model.index(3, 2)), QVariant());
+ QCOMPARE(model.data(model.index(3, 3)), QVariant());
+
+ // Now add a column at 0 and 2
+ model.insertColumn(0);
+ model.insertColumn(2);
+
+ QCOMPARE(model.rowCount(), 3);
+ QCOMPARE(model.columnCount(), 5);
+
+ QCOMPARE(model.data(model.index(0, 0)), QVariant());
+ QCOMPARE(model.data(model.index(0, 1)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 2)), QVariant());
+ QCOMPARE(model.data(model.index(0, 3)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 4)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 5)), QVariant());
+
+ QCOMPARE(model.data(model.index(1, 0)), QVariant());
+ QCOMPARE(model.data(model.index(1, 1)).toInt(), 2);
+ QCOMPARE(model.data(model.index(1, 2)), QVariant());
+ QCOMPARE(model.data(model.index(1, 3)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(1, 4)).toInt(), 2);
+ QCOMPARE(model.data(model.index(1, 5)), QVariant());
+
+ QCOMPARE(model.data(model.index(2, 0)), QVariant());
+ QCOMPARE(model.data(model.index(2, 1)).toInt(), 3);
+ QCOMPARE(model.data(model.index(2, 2)), QVariant());
+ QCOMPARE(model.data(model.index(2, 3)).toString(), QString("vohi"));
+ QCOMPARE(model.data(model.index(2, 4)).toInt(), 3);
+ QCOMPARE(model.data(model.index(2, 5)), QVariant());
+
+ QCOMPARE(model.data(model.index(3, 0)), QVariant());
+ QCOMPARE(model.data(model.index(3, 1)), QVariant());
+ QCOMPARE(model.data(model.index(3, 2)), QVariant());
+ QCOMPARE(model.data(model.index(3, 3)), QVariant());
+ QCOMPARE(model.data(model.index(3, 4)), QVariant());
+ QCOMPARE(model.data(model.index(3, 5)), QVariant());
+}
+
+void tst_QSqlTableModel::setRecord()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QList<QSqlTableModel::EditStrategy> policies = QList<QSqlTableModel::EditStrategy>() << QSqlTableModel::OnFieldChange << QSqlTableModel::OnRowChange << QSqlTableModel::OnManualSubmit;
+
+ QString Xsuffix;
+ foreach( QSqlTableModel::EditStrategy submitpolicy, policies) {
+
+ QSqlTableModel model(0, db);
+ model.setEditStrategy((QSqlTableModel::EditStrategy)submitpolicy);
+ model.setTable(test3);
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ for (int i = 0; i < model.rowCount(); ++i) {
+ QSignalSpy spy(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex)));
+
+ QSqlRecord rec = model.record(i);
+ rec.setValue(1, rec.value(1).toString() + 'X');
+ rec.setValue(2, rec.value(2).toString() + 'X');
+ QVERIFY(model.setRecord(i, rec));
+
+ if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnManualSubmit) {
+ // setRecord should emit dataChanged() itself for manualSubmit
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).count(), 2);
+ QCOMPARE(qvariant_cast<QModelIndex>(spy.at(0).at(0)), model.index(i, 0));
+ QCOMPARE(qvariant_cast<QModelIndex>(spy.at(0).at(1)), model.index(i, rec.count() - 1));
+ QVERIFY(model.submitAll());
+ } else if ((QSqlTableModel::EditStrategy)submitpolicy == QSqlTableModel::OnRowChange && i == model.rowCount() -1)
+ model.submit();
+ else {
+ // dataChanged() is not emitted when submitAll() is called
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy.at(0).count(), 2);
+ QCOMPARE(qvariant_cast<QModelIndex>(spy.at(0).at(0)), model.index(i, 1));
+ QCOMPARE(qvariant_cast<QModelIndex>(spy.at(0).at(1)), model.index(i, 1));
+ }
+ }
+
+ Xsuffix.append('X');
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("foo").append(Xsuffix));
+ QCOMPARE(model.data(model.index(0, 2)).toString(), QString("bar").append(Xsuffix));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("baz").append(Xsuffix));
+ QCOMPARE(model.data(model.index(1, 2)).toString(), QString("joe").append(Xsuffix));
+ }
+}
+
+void tst_QSqlTableModel::insertRow()
+{
+ QFETCH(QString, dbName);
+ QFETCH(int, submitpolicy_i);
+ QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i;
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ model.setEditStrategy(submitpolicy);
+ model.setTable(test);
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 1);
+ QCOMPARE(model.data(model.index(1, 0)).toInt(), 2);
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(1, 2)).toInt(), 2);
+ QCOMPARE(model.data(model.index(2, 0)).toInt(), 3);
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi"));
+ QCOMPARE(model.data(model.index(2, 2)).toInt(), 3);
+
+ QVERIFY(model.insertRow(2));
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 1);
+ QCOMPARE(model.data(model.index(1, 0)).toInt(), 2);
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(1, 2)).toInt(), 2);
+ QCOMPARE(model.data(model.index(2, 0)).toInt(), 0);
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString());
+ QCOMPARE(model.data(model.index(2, 2)).toInt(), 0);
+ QCOMPARE(model.data(model.index(3, 0)).toInt(), 3);
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("vohi"));
+ QCOMPARE(model.data(model.index(3, 2)).toInt(), 3);
+
+ QSqlRecord rec = model.record(1);
+ rec.setValue(0, 42);
+ rec.setValue(1, QString("francis"));
+
+ // FieldChange updates immediately and resorts
+ // Row/Manual submit does not resort
+ QVERIFY(model.setRecord(2, rec));
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 1);
+ QCOMPARE(model.data(model.index(1, 0)).toInt(), 2);
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(1, 2)).toInt(), 2);
+
+ // See comment above setRecord
+ if (submitpolicy == QSqlTableModel::OnFieldChange) {
+ QCOMPARE(model.data(model.index(2, 0)).toInt(), 3);
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi"));
+ QCOMPARE(model.data(model.index(2, 2)).toInt(), 3);
+ QCOMPARE(model.data(model.index(3, 0)).toInt(), 42);
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("francis"));
+ QCOMPARE(model.data(model.index(3, 2)).toInt(), 2);
+ } else {
+ QCOMPARE(model.data(model.index(2, 0)).toInt(), 42);
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString("francis"));
+ QCOMPARE(model.data(model.index(2, 2)).toInt(), 2);
+ QCOMPARE(model.data(model.index(3, 0)).toInt(), 3);
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("vohi"));
+ QCOMPARE(model.data(model.index(3, 2)).toInt(), 3);
+ }
+
+ QVERIFY(model.submitAll());
+
+ // After the submit we should have the resorted view
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(0, 2)).toInt(), 1);
+ QCOMPARE(model.data(model.index(1, 0)).toInt(), 2);
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(1, 2)).toInt(), 2);
+ QCOMPARE(model.data(model.index(2, 0)).toInt(), 3);
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi"));
+ QCOMPARE(model.data(model.index(2, 2)).toInt(), 3);
+ QCOMPARE(model.data(model.index(3, 0)).toInt(), 42);
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("francis"));
+ QCOMPARE(model.data(model.index(3, 2)).toInt(), 2);
+
+}
+
+void tst_QSqlTableModel::insertRecord()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ model.setTable(test);
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QSqlRecord rec = model.record();
+ rec.setValue(0, 42);
+ rec.setValue(1, QString("vohi"));
+ rec.setValue(2, 1);
+ QVERIFY(model.insertRecord(1, rec));
+ QCOMPARE(model.rowCount(), 4);
+
+ QCOMPARE(model.data(model.index(1, 0)).toInt(), 42);
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("vohi"));
+ QCOMPARE(model.data(model.index(1, 2)).toInt(), 1);
+
+ model.revertAll();
+ model.setEditStrategy(QSqlTableModel::OnRowChange);
+
+ QVERIFY(model.insertRecord(-1, rec));
+
+ QCOMPARE(model.data(model.index(3, 0)).toInt(), 42);
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("vohi"));
+ QCOMPARE(model.data(model.index(3, 2)).toInt(), 1);
+}
+
+void tst_QSqlTableModel::insertMultiRecords()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ model.setTable(test);
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.rowCount(), 3);
+
+ QVERIFY(model.insertRow(2));
+
+ QCOMPARE(model.data(model.index(2, 0)), QVariant(model.record().field(0).type()));
+ QCOMPARE(model.data(model.index(2, 1)), QVariant(model.record().field(1).type()));
+ QCOMPARE(model.data(model.index(2, 2)), QVariant(model.record().field(2).type()));
+
+ QVERIFY(model.insertRow(3));
+ QVERIFY(model.insertRow(0));
+
+ QCOMPARE(model.data(model.index(5, 0)).toInt(), 3);
+ QCOMPARE(model.data(model.index(5, 1)).toString(), QString("vohi"));
+ QCOMPARE(model.data(model.index(5, 2)).toInt(), 3);
+
+ QVERIFY(model.setData(model.index(0, 0), QVariant(42)));
+ QVERIFY(model.setData(model.index(3, 0), QVariant(43)));
+ QVERIFY(model.setData(model.index(4, 0), QVariant(44)));
+ QVERIFY(model.setData(model.index(4, 1), QVariant(QLatin1String("gunnar"))));
+ QVERIFY(model.setData(model.index(4, 2), QVariant(1)));
+
+ QVERIFY(model.submitAll());
+ model.clear();
+ model.setTable(test);
+ model.setSort(0, Qt::AscendingOrder);
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(1, 0)).toInt(), 2);
+ QCOMPARE(model.data(model.index(2, 0)).toInt(), 3);
+ QCOMPARE(model.data(model.index(3, 0)).toInt(), 42);
+ QCOMPARE(model.data(model.index(4, 0)).toInt(), 43);
+ QCOMPARE(model.data(model.index(5, 0)).toInt(), 44);
+ QCOMPARE(model.data(model.index(5, 1)).toString(), QString("gunnar"));
+ QCOMPARE(model.data(model.index(5, 2)).toInt(), 1);
+}
+
+void tst_QSqlTableModel::submitAll()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ model.setTable(test);
+ model.setSort(0, Qt::AscendingOrder);
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ QVERIFY_SQL(model, select());
+
+ QVERIFY(model.setData(model.index(0, 1), "harry2", Qt::EditRole));
+ QVERIFY(model.setData(model.index(1, 1), "trond2", Qt::EditRole));
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry2"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond2"));
+
+ QVERIFY_SQL(model, submitAll());
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry2"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond2"));
+
+ QVERIFY(model.setData(model.index(0, 1), "harry", Qt::EditRole));
+ QVERIFY(model.setData(model.index(1, 1), "trond", Qt::EditRole));
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
+
+ QVERIFY_SQL(model, submitAll());
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
+}
+
+void tst_QSqlTableModel::removeRow()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ model.setTable(test);
+ model.setSort(0, Qt::AscendingOrder);
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.rowCount(), 3);
+
+ // headerDataChanged must be emitted by the model when the edit strategy is OnManualSubmit,
+ // when OnFieldChange or OnRowChange it's not needed because the model will re-select.
+ qRegisterMetaType<Qt::Orientation>("Qt::Orientation");
+ QSignalSpy headerDataChangedSpy(&model, SIGNAL(headerDataChanged(Qt::Orientation, int, int)));
+
+ QVERIFY(model.removeRow(1));
+ QCOMPARE(headerDataChangedSpy.count(), 1);
+ QCOMPARE(*static_cast<const Qt::Orientation *>(headerDataChangedSpy.at(0).value(0).constData()), Qt::Vertical);
+ QCOMPARE(headerDataChangedSpy.at(0).at(1).toInt(), 1);
+ QCOMPARE(headerDataChangedSpy.at(0).at(2).toInt(), 1);
+ QVERIFY(model.submitAll());
+ QCOMPARE(model.rowCount(), 2);
+
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+ QCOMPARE(model.data(model.index(1, 0)).toInt(), 3);
+ model.clear();
+
+ recreateTestTables();
+
+ model.setTable(test);
+ model.setEditStrategy(QSqlTableModel::OnRowChange);
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.rowCount(), 3);
+
+ headerDataChangedSpy.clear();
+ QVERIFY(model.removeRow(1));
+ QCOMPARE(headerDataChangedSpy.count(), 0);
+ QCOMPARE(model.rowCount(), 2);
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("vohi"));
+}
+
+void tst_QSqlTableModel::removeRows()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ model.setTable(test);
+ model.setSort(0, Qt::AscendingOrder);
+ model.setEditStrategy(QSqlTableModel::OnFieldChange);
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.rowCount(), 3);
+
+ QSignalSpy beforeDeleteSpy(&model, SIGNAL(beforeDelete(int)));
+
+ // Make sure wrong stuff is ok
+ QVERIFY(!model.removeRows(-1,1)); // negative start
+ QVERIFY(!model.removeRows(-1, 0)); // negative start, and zero count
+ QVERIFY(!model.removeRows(1, 0)); // zero count
+ QVERIFY(!model.removeRows(5, 1)); // past end (causes a beforeDelete to be emitted)
+ QVERIFY(!model.removeRows(1, 0, model.index(2, 0))); // can't pass a valid modelindex
+
+ QVERIFY_SQL(model, removeRows(0, 2));
+ QCOMPARE(beforeDeleteSpy.count(), 3);
+ QVERIFY(beforeDeleteSpy.at(0).at(0).toInt() == 5);
+ QVERIFY(beforeDeleteSpy.at(1).at(0).toInt() == 0);
+ QVERIFY(beforeDeleteSpy.at(2).at(0).toInt() == 1);
+ QCOMPARE(model.rowCount(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("vohi"));
+ model.clear();
+
+ recreateTestTables();
+ model.setTable(test);
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.rowCount(), 3);
+ beforeDeleteSpy.clear();
+
+ // When the edit strategy is OnManualSubmit the beforeDelete() signal
+ // isn't emitted until submitAll() is called.
+
+ QVERIFY(!model.removeRows(-1,1)); // negative start
+ QVERIFY(!model.removeRows(-1, 0)); // negative start, and zero count
+ QVERIFY(!model.removeRows(1, 0)); // zero count
+ QVERIFY(!model.removeRows(5, 1)); // past end (DOESN'T cause a beforeDelete to be emitted)
+ QVERIFY(!model.removeRows(1, 0, model.index(2, 0))); // can't pass a valid modelindex
+
+ qRegisterMetaType<Qt::Orientation>("Qt::Orientation");
+ QSignalSpy headerDataChangedSpy(&model, SIGNAL(headerDataChanged(Qt::Orientation, int, int)));
+ QVERIFY(model.removeRows(0, 2, QModelIndex()));
+ QCOMPARE(headerDataChangedSpy.count(), 2);
+ QCOMPARE(headerDataChangedSpy.at(0).at(1).toInt(), 0);
+ QCOMPARE(headerDataChangedSpy.at(0).at(2).toInt(), 0);
+ QCOMPARE(headerDataChangedSpy.at(1).at(1).toInt(), 1);
+ QCOMPARE(headerDataChangedSpy.at(1).at(2).toInt(), 1);
+ QCOMPARE(model.rowCount(), 3);
+ QVERIFY(beforeDeleteSpy.count() == 0);
+ QVERIFY(model.submitAll());
+ QVERIFY(beforeDeleteSpy.count() == 2);
+ QVERIFY(beforeDeleteSpy.at(0).at(0).toInt() == 0);
+ QVERIFY(beforeDeleteSpy.at(1).at(0).toInt() == 1);
+ QCOMPARE(model.rowCount(), 1);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("vohi"));
+}
+
+void tst_QSqlTableModel::removeInsertedRow()
+{
+ QFETCH(QString, dbName);
+ QFETCH(int, submitpolicy_i);
+ QSqlTableModel::EditStrategy submitpolicy = (QSqlTableModel::EditStrategy) submitpolicy_i;
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ model.setTable(test);
+ model.setSort(0, Qt::AscendingOrder);
+
+ model.setEditStrategy(submitpolicy);
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.rowCount(), 3);
+
+ QVERIFY(model.insertRow(1));
+ QCOMPARE(model.rowCount(), 4);
+
+ QVERIFY(model.removeRow(1));
+ QCOMPARE(model.rowCount(), 3);
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi"));
+
+ // Now insert a row with a null, and check that removing it also works (QTBUG-15979 etc)
+ model.insertRow(1);
+ model.setData(model.index(1,0), 55);
+ model.setData(model.index(1,1), QString("null columns"));
+ model.setData(model.index(1,2), QVariant());
+
+ model.submitAll();
+
+ QCOMPARE(model.rowCount(), 4);
+ QCOMPARE(model.data(model.index(3, 0)).toInt(), 55);
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("null columns"));
+ QCOMPARE(model.data(model.index(3, 2)).isNull(), true);
+
+ QVERIFY(model.removeRow(3));
+ model.submitAll();
+ QCOMPARE(model.rowCount(), 3);
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi"));
+}
+
+void tst_QSqlTableModel::removeInsertedRows()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ model.setTable(test);
+ model.setSort(0, Qt::AscendingOrder);
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit); // you can't insert more than one row otherwise
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.rowCount(), 3);
+
+ // First put two empty rows, and remove them one by one
+ QVERIFY(model.insertRows(1, 2));
+ QCOMPARE(model.rowCount(), 5);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString());
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString());
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi"));
+
+ QVERIFY(model.removeRow(1));
+ QCOMPARE(model.rowCount(), 4);
+
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString());
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("vohi"));
+
+ QVERIFY(model.removeRow(1));
+ QCOMPARE(model.rowCount(), 3);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi"));
+
+ // Now put two empty rows, and remove them all at once
+ QVERIFY(model.insertRows(1, 2));
+ QCOMPARE(model.rowCount(), 5);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString());
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString());
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi"));
+
+ QVERIFY(model.removeRows(1, 2));
+ QCOMPARE(model.rowCount(), 3);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString("vohi"));
+
+
+ // Now put two empty rows, and remove one good and two empty
+ QVERIFY(model.insertRows(1, 2));
+ QCOMPARE(model.rowCount(), 5);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString());
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString());
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi"));
+
+ QVERIFY(model.removeRows(0, 3));
+ QVERIFY(model.submitAll()); // otherwise the remove of the real row doesn't work
+
+ QCOMPARE(model.rowCount(), 2);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("vohi"));
+
+ // Reset back again
+ model.clear();
+ recreateTestTables();
+ model.setTable(test);
+ model.setSort(0, Qt::AscendingOrder);
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit); // you can't insert more than one row otherwise
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.rowCount(), 3);
+
+ // Now two empty and one good
+ QVERIFY(model.insertRows(1, 2));
+ QCOMPARE(model.rowCount(), 5);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString());
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString());
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi"));
+
+ QVERIFY(model.removeRows(1, 3));
+ QVERIFY(model.submitAll());
+ QCOMPARE(model.rowCount(), 2);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("vohi"));
+
+ // Reset back again
+ model.clear();
+ recreateTestTables();
+ model.setTable(test);
+ model.setSort(0, Qt::AscendingOrder);
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit); // you can't insert more than one row otherwise
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.rowCount(), 3);
+
+ // one empty, one good, one empty
+ QVERIFY(model.insertRows(1, 1));
+ QVERIFY(model.insertRows(3, 1));
+ QCOMPARE(model.rowCount(), 5);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString());
+ QCOMPARE(model.data(model.index(2, 1)).toString(), QString("trond"));
+ QCOMPARE(model.data(model.index(3, 1)).toString(), QString());
+ QCOMPARE(model.data(model.index(4, 1)).toString(), QString("vohi"));
+
+ QVERIFY(model.removeRows(1, 3));
+ QVERIFY(model.submitAll());
+ QCOMPARE(model.rowCount(), 2);
+ QCOMPARE(model.data(model.index(0, 1)).toString(), QString("harry"));
+ QCOMPARE(model.data(model.index(1, 1)).toString(), QString("vohi"));
+}
+
+void tst_QSqlTableModel::emptyTable()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ QCOMPARE(model.rowCount(), 0);
+ QCOMPARE(model.columnCount(), 0);
+
+ model.setTable(qTableName("emptytable", __FILE__));
+ QCOMPARE(model.rowCount(), 0);
+ QCOMPARE(model.columnCount(), 1);
+
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.rowCount(), 0);
+ QCOMPARE(model.columnCount(), 1);
+}
+
+void tst_QSqlTableModel::tablesAndSchemas()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlQuery q(db);
+ q.exec("DROP SCHEMA " + qTableName("testschema", __FILE__) + " CASCADE");
+ QVERIFY_SQL( q, exec("create schema " + qTableName("testschema", __FILE__)));
+ QString tableName = qTableName("testschema", __FILE__) + '.' + qTableName("testtable", __FILE__);
+ QVERIFY_SQL( q, exec("create table " + tableName + "(id int)"));
+ QVERIFY_SQL( q, exec("insert into " + tableName + " values(1)"));
+ QVERIFY_SQL( q, exec("insert into " + tableName + " values(2)"));
+
+ QSqlTableModel model(0, db);
+ model.setTable(tableName);
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.rowCount(), 2);
+ QCOMPARE(model.columnCount(), 1);
+}
+
+void tst_QSqlTableModel::whitespaceInIdentifiers()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ if (!testWhiteSpaceNames(db.driverName()))
+ QSKIP("DBMS doesn't support whitespaces in identifiers", SkipSingle);
+
+ QString tableName = qTableName("qtestw hitespace", db.driver());
+
+ QSqlTableModel model(0, db);
+ model.setTable(tableName);
+ QVERIFY_SQL(model, select());
+}
+
+void tst_QSqlTableModel::primaryKeyOrder()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlQuery q(db);
+
+ if(tst_Databases::isPostgreSQL(db))
+ QVERIFY_SQL( q, exec("set client_min_messages='warning'"));
+
+ QVERIFY_SQL( q, exec("create table "+qTableName("foo", __FILE__)+"(a varchar(20), id int not null primary key, b varchar(20))"));
+
+ QSqlTableModel model(0, db);
+ model.setTable(qTableName("foo", __FILE__));
+
+ QSqlIndex pk = model.primaryKey();
+ QCOMPARE(pk.count(), 1);
+ QCOMPARE(pk.fieldName(0), QLatin1String("id"));
+
+ QVERIFY(model.insertRow(0));
+ QVERIFY(model.setData(model.index(0, 0), "hello"));
+ QVERIFY(model.setData(model.index(0, 1), 42));
+ QVERIFY(model.setData(model.index(0, 2), "blah"));
+ QVERIFY_SQL(model, submitAll());
+
+ QVERIFY(model.setData(model.index(0, 1), 43));
+ QVERIFY_SQL(model, submitAll());
+
+ QCOMPARE(model.data(model.index(0, 1)).toInt(), 43);
+}
+
+void tst_QSqlTableModel::setInvalidFilter()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ // set an invalid filter, make sure it fails
+ QSqlTableModel model(0, db);
+ model.setTable(test);
+ model.setFilter("blahfahsel");
+
+ QCOMPARE(model.filter(), QString("blahfahsel"));
+ QVERIFY(!model.select());
+
+ // set a valid filter later, make sure if passes
+ model.setFilter("id = 1");
+ QVERIFY_SQL(model, select());
+}
+
+void tst_QSqlTableModel::setFilter()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ model.setTable(test);
+ model.setFilter("id = 1");
+ QCOMPARE(model.filter(), QString("id = 1"));
+ QVERIFY_SQL(model, select());
+
+ QCOMPARE(model.rowCount(), 1);
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 1);
+
+ QSignalSpy rowsRemovedSpy(&model, SIGNAL(rowsRemoved(QModelIndex,int,int)));
+ QSignalSpy rowsAboutToBeRemovedSpy(&model,
+ SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)));
+ QSignalSpy rowsInsertedSpy(&model, SIGNAL(rowsInserted(QModelIndex,int,int)));
+ QSignalSpy rowsAboutToBeInsertedSpy(&model,
+ SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)));
+ model.setFilter("id = 2");
+
+ // check the signals
+ QCOMPARE(rowsAboutToBeRemovedSpy.count(), 1);
+ QCOMPARE(rowsRemovedSpy.count(), 1);
+ QCOMPARE(rowsAboutToBeInsertedSpy.count(), 1);
+ QCOMPARE(rowsInsertedSpy.count(), 1);
+ QList<QVariant> args = rowsAboutToBeRemovedSpy.takeFirst();
+ QCOMPARE(args.count(), 3);
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), QModelIndex());
+ QCOMPARE(args.at(1).toInt(), 0);
+ QCOMPARE(args.at(2).toInt(), 0);
+ args = rowsRemovedSpy.takeFirst();
+ QCOMPARE(args.count(), 3);
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), QModelIndex());
+ QCOMPARE(args.at(1).toInt(), 0);
+ QCOMPARE(args.at(2).toInt(), 0);
+ args = rowsInsertedSpy.takeFirst();
+ QCOMPARE(args.count(), 3);
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), QModelIndex());
+ QCOMPARE(args.at(1).toInt(), 0);
+ QCOMPARE(args.at(2).toInt(), 0);
+ args = rowsAboutToBeInsertedSpy.takeFirst();
+ QCOMPARE(args.count(), 3);
+ QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), QModelIndex());
+ QCOMPARE(args.at(1).toInt(), 0);
+ QCOMPARE(args.at(2).toInt(), 0);
+
+ QCOMPARE(model.rowCount(), 1);
+ QCOMPARE(model.data(model.index(0, 0)).toInt(), 2);
+}
+
+void tst_QSqlTableModel::sqlite_bigTable()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ const QString bigtable(qTableName("bigtable", __FILE__));
+
+ bool hasTransactions = db.driver()->hasFeature(QSqlDriver::Transactions);
+ if (hasTransactions) QVERIFY(db.transaction());
+ QSqlQuery q(db);
+ QVERIFY_SQL( q, exec("create table "+bigtable+"(id int primary key, name varchar)"));
+ QVERIFY_SQL( q, prepare("insert into "+bigtable+"(id, name) values (?, ?)"));
+ QTime startTime;
+ startTime.start();
+ for (int i = 0; i < 10000; ++i) {
+ q.addBindValue(i);
+ q.addBindValue(QString::number(i));
+ if(i%1000 == 0 && startTime.elapsed() > 5000)
+ qDebug() << i << "records written";
+ QVERIFY_SQL( q, exec());
+ }
+ q.clear();
+ if (hasTransactions) QVERIFY(db.commit());
+
+ QSqlTableModel model(0, db);
+ model.setTable(bigtable);
+ QVERIFY_SQL(model, select());
+
+ QSqlRecord rec = model.record();
+ rec.setValue("id", 424242);
+ rec.setValue("name", "Guillaume");
+ QVERIFY_SQL(model, insertRecord(-1, rec));
+
+ model.clear();
+}
+
+// For task 118547: couldn't insert records unless select()
+// had first been called.
+void tst_QSqlTableModel::insertRecordBeforeSelect()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ model.setTable(test);
+ QCOMPARE(model.lastError().type(), QSqlError::NoError);
+
+ QSqlRecord buffer = model.record();
+ buffer.setValue("id", 13);
+ buffer.setValue("name", QString("The Lion King"));
+ buffer.setValue("title", 0);
+ QVERIFY_SQL(model, insertRecord(-1, buffer));
+
+ buffer.setValue("id", 26);
+ buffer.setValue("name", QString("T. Leary"));
+ buffer.setValue("title", 0);
+ QVERIFY_SQL(model, insertRecord(1, buffer));
+
+ int rowCount = model.rowCount();
+ model.clear();
+ QCOMPARE(model.rowCount(), 0);
+
+ QSqlTableModel model2(0, db);
+ model2.setTable(test);
+ QVERIFY_SQL(model2, select());
+ QCOMPARE(model2.rowCount(), rowCount);
+}
+
+// For task 118547: set errors if table doesn't exist and if records
+// are inserted and submitted on a non-existing table.
+void tst_QSqlTableModel::submitAllOnInvalidTable()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+
+ // setTable returns a void, so the error can only be caught by
+ // manually checking lastError(). ### Qt5: This should be changed!
+ model.setTable(qTableName("invalidTable", __FILE__));
+ QCOMPARE(model.lastError().type(), QSqlError::StatementError);
+
+ // This will give us an empty record which is expected behavior
+ QSqlRecord buffer = model.record();
+ buffer.setValue("bogus", 1000);
+ buffer.setValue("bogus2", QString("I will go nowhere!"));
+
+ // Inserting the record into the *model* will work (OnManualSubmit)
+ QVERIFY_SQL(model, insertRecord(-1, buffer));
+
+ // The submit and select shall fail because the table doesn't exist
+ QEXPECT_FAIL("", "The table doesn't exist: submitAll() shall fail",
+ Continue);
+ QVERIFY_SQL(model, submitAll());
+ QEXPECT_FAIL("", "The table doesn't exist: select() shall fail",
+ Continue);
+ QVERIFY_SQL(model, select());
+}
+
+// For task 147575: the rowsRemoved signal emitted from the model was lying
+void tst_QSqlTableModel::insertRecordsInLoop()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ model.setTable(test);
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ model.select();
+
+ QSqlRecord record = model.record();
+ record.setValue(0, 10);
+ record.setValue(1, "Testman");
+ record.setValue(2, 1);
+
+ QSignalSpy spyRowsRemoved(&model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)));
+ QSignalSpy spyRowsInserted(&model, SIGNAL(rowsInserted(const QModelIndex &, int, int)));
+ for (int i = 0; i < 10; i++) {
+ QVERIFY(model.insertRecord(model.rowCount(), record));
+ QCOMPARE(spyRowsInserted.at(i).at(1).toInt(), i+3); // The table already contains three rows
+ QCOMPARE(spyRowsInserted.at(i).at(2).toInt(), i+3);
+ }
+ model.submitAll(); // submitAll() calls select() which clears and repopulates the table
+
+ int firstRowIndex = 0, lastRowIndex = 12;
+ QCOMPARE(spyRowsRemoved.count(), 1);
+ QCOMPARE(spyRowsRemoved.at(0).at(1).toInt(), firstRowIndex);
+ QCOMPARE(spyRowsRemoved.at(0).at(2).toInt(), lastRowIndex);
+
+ QCOMPARE(spyRowsInserted.at(10).at(1).toInt(), firstRowIndex);
+ QCOMPARE(spyRowsInserted.at(10).at(2).toInt(), lastRowIndex);
+ QCOMPARE(spyRowsInserted.count(), 11);
+
+ QCOMPARE(model.rowCount(), 13);
+ QCOMPARE(model.columnCount(), 3);
+}
+
+void tst_QSqlTableModel::sqlite_attachedDatabase()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ if(db.databaseName() == ":memory:")
+ QSKIP(":memory: database, skipping test", SkipSingle);
+
+ QSqlDatabase attachedDb = QSqlDatabase::cloneDatabase(db, db.driverName() + QLatin1String("attached"));
+ attachedDb.setDatabaseName(db.databaseName()+QLatin1String("attached.dat"));
+ QVERIFY_SQL(attachedDb, open());
+ QSqlQuery q(attachedDb);
+ tst_Databases::safeDropTables(attachedDb, QStringList() << "atest" << "atest2");
+ QVERIFY_SQL( q, exec("CREATE TABLE atest(id int, text varchar(20))"));
+ QVERIFY_SQL( q, exec("CREATE TABLE atest2(id int, text varchar(20))"));
+ QVERIFY_SQL( q, exec("INSERT INTO atest VALUES(1, 'attached-atest')"));
+ QVERIFY_SQL( q, exec("INSERT INTO atest2 VALUES(2, 'attached-atest2')"));
+
+ QSqlQuery q2(db);
+ tst_Databases::safeDropTable(db, "atest");
+ QVERIFY_SQL(q2, exec("CREATE TABLE atest(id int, text varchar(20))"));
+ QVERIFY_SQL(q2, exec("INSERT INTO atest VALUES(3, 'main')"));
+ QVERIFY_SQL(q2, exec("ATTACH DATABASE \""+attachedDb.databaseName()+"\" as adb"));
+
+ // This should query the table in the attached database (schema supplied)
+ QSqlTableModel model(0, db);
+ model.setTable("adb.atest");
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.rowCount(), 1);
+ QCOMPARE(model.data(model.index(0, 0), Qt::DisplayRole).toInt(), 1);
+ QCOMPARE(model.data(model.index(0, 1), Qt::DisplayRole).toString(), QLatin1String("attached-atest"));
+
+ // This should query the table in the attached database (unique tablename)
+ model.setTable("atest2");
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.rowCount(), 1);
+ QCOMPARE(model.data(model.index(0, 0), Qt::DisplayRole).toInt(), 2);
+ QCOMPARE(model.data(model.index(0, 1), Qt::DisplayRole).toString(), QLatin1String("attached-atest2"));
+
+ // This should query the table in the main database (tables in main db has 1st priority)
+ model.setTable("atest");
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.rowCount(), 1);
+ QCOMPARE(model.data(model.index(0, 0), Qt::DisplayRole).toInt(), 3);
+ QCOMPARE(model.data(model.index(0, 1), Qt::DisplayRole).toString(), QLatin1String("main"));
+}
+
+
+void tst_QSqlTableModel::tableModifyWithBlank()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ model.setTable(qTableName("test4", __FILE__));
+ model.select();
+
+ //generate a time stamp for the test. Add one second to the current time to make sure
+ //it is different than the QSqlQuery test.
+ QString timeString=QDateTime::currentDateTime().addSecs(1).toString(Qt::ISODate);
+
+ //insert a new row, with column0 being the timestamp.
+ //Should be equivalent to QSqlQuery INSERT INTO... command)
+ QVERIFY_SQL(model, insertRow(0));
+ QVERIFY_SQL(model, setData(model.index(0,0),timeString));
+ QVERIFY_SQL(model, submitAll());
+
+ //set a filter on the table so the only record we get is the one we just made
+ //I could just do another setData command, but I want to make sure the TableModel
+ //matches exactly what is stored in the database
+ model.setFilter("column1='"+timeString+"'"); //filter to get just the newly entered row
+ QVERIFY_SQL(model, select());
+
+ //Make sure we only get one record, and that it is the one we just made
+ QCOMPARE(model.rowCount(), 1); //verify only one entry
+ QCOMPARE(model.record(0).value(0).toString(), timeString); //verify correct record
+
+ //At this point we know that the initial value (timestamp) was succsefully stored in the database
+ //Attempt to modify the data in the new record
+ //equivalent to query.exec("update test set column3="... command in direct test
+ //set the data in the first column to "col1ModelData"
+ QVERIFY_SQL(model, setData(model.index(0,1), "col1ModelData"));
+
+ //do a quick check to make sure that the setData command properly set the value in the model
+ QCOMPARE(model.record(0).value(1).toString(), QLatin1String("col1ModelData"));
+
+ //submit the changed data to the database
+ //This is where I have been getting errors.
+ QVERIFY_SQL(model, submitAll());
+
+ //make sure the model has the most current data for our record
+ QVERIFY_SQL(model, select());
+
+ //verify that our new record was the only record returned
+ QCOMPARE(model.rowCount(), 1);
+
+ //And that the record returned is, in fact, our test record.
+ QCOMPARE(model.record(0).value(0).toString(), timeString);
+
+ //Make sure the value of the first column matches what we set it to previously.
+ QCOMPARE(model.record(0).value(1).toString(), QLatin1String("col1ModelData"));
+}
+
+void tst_QSqlTableModel::removeColumnAndRow()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlTableModel model(0, db);
+ model.setTable(test);
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ QVERIFY_SQL(model, select());
+ QCOMPARE(model.rowCount(), 3);
+ QCOMPARE(model.columnCount(), 3);
+
+ QVERIFY(model.removeColumn(0));
+ QVERIFY(model.removeRow(0));
+ QVERIFY(model.submitAll());
+ QCOMPARE(model.rowCount(), 2);
+ QCOMPARE(model.columnCount(), 2);
+
+ // check with another table because the model has been modified
+ // but not the sql table
+ QSqlTableModel model2(0, db);
+ model2.setTable(test);
+ QVERIFY_SQL(model2, select());
+ QCOMPARE(model2.rowCount(), 2);
+ QCOMPARE(model2.columnCount(), 3);
+}
+
+void tst_QSqlTableModel::insertBeforeDelete()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+
+ QSqlQuery q(db);
+ QVERIFY_SQL( q, exec("insert into " + test + " values(9, 'andrew', 9)"));
+ QVERIFY_SQL( q, exec("insert into " + test + " values(10, 'justin', 10)"));
+
+ QSqlTableModel model(0, db);
+ model.setTable(test);
+ model.setEditStrategy(QSqlTableModel::OnManualSubmit);
+ QVERIFY_SQL(model, select());
+
+ QSqlRecord rec = model.record();
+ rec.setValue(0, 4);
+ rec.setValue(1, QString("bill"));
+ rec.setValue(2, 4);
+ QVERIFY_SQL(model, insertRecord(4, rec));
+
+ QVERIFY_SQL(model, removeRow(5));
+ QVERIFY_SQL(model, submitAll());
+ QCOMPARE(model.rowCount(), 5);
+}
+
+QTEST_MAIN(tst_QSqlTableModel)
+#include "tst_qsqltablemodel.moc"