From ea6675374fa6e94bd4cf10613c85cee2c724bcdc Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 23 Jan 2018 10:25:54 -0800 Subject: [PATCH 1/4] QString: fix comparisons to null strings in ucstricmp Commit 8f52ad9fe084eee26869e4a94a678076845a6f58 ("ucstricmp: compare null and empty strings equal") made sure empties and nulls would compare equally, but may have broken the null vs non-empty comparison (which was not tested). The commit message also said that it expected all callers to handle null before calling into those functions, but that's not the case for QStringView created from a null QString: the incoming "a" pointer was null. So just remove the checks for null pointers and rely on the size checks doing the right thing. [ChangeLog][QtCore][QString] Fixed a regression from 5.9 that caused comparing default-constructed QStrings to be sorted after non-empty strings. Task-number: QTBUG-65939 Change-Id: I56b444f9d6274221a3b7fffd150c83ad46c599b6 Reviewed-by: Lars Knoll --- src/corelib/tools/qstring.cpp | 9 --------- tests/auto/corelib/tools/qstring/tst_qstring.cpp | 8 +++++++- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 30f8948eec..80c8510fa4 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -423,10 +423,6 @@ static int ucstricmp(const QChar *a, const QChar *ae, const QChar *b, const QCha { if (a == b) return (ae - be); - if (a == 0) - return be - b; - if (b == 0) - return a - ae; const QChar *e = ae; if (be - b < ae - a) @@ -455,11 +451,6 @@ static int ucstricmp(const QChar *a, const QChar *ae, const QChar *b, const QCha // Case-insensitive comparison between a Unicode string and a QLatin1String static int ucstricmp(const QChar *a, const QChar *ae, const char *b, const char *be) { - if (!a) - return be - b; - if (!b) - return a - ae; - auto e = ae; if (be - b < ae - a) e = a + (be - b); diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index 70ccc72630..a028391b06 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -6043,8 +6043,14 @@ void tst_QString::compare_data() QTest::addColumn("csr"); // case sensitive result QTest::addColumn("cir"); // case insensitive result - // null strings + QTest::newRow("null-null") << QString() << QString() << 0 << 0; + QTest::newRow("text-null") << QString("a") << QString() << 1 << 1; + QTest::newRow("null-text") << QString() << QString("a") << -1 << -1; + QTest::newRow("null-empty") << QString() << QString("") << 0 << 0; + QTest::newRow("empty-null") << QString("") << QString() << 0 << 0; + + // empty strings QTest::newRow("data0") << QString("") << QString("") << 0 << 0; QTest::newRow("data1") << QString("a") << QString("") << 1 << 1; QTest::newRow("data2") << QString("") << QString("a") << -1 << -1; From 75c22d459872aca47ac2bb9e0e88d63f4f0b5d38 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Wed, 7 Feb 2018 14:08:17 +0100 Subject: [PATCH 2/4] QCocoaWindow: be more careful when flushing events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flushing the QPA event queue is problematic since we can then end up delivering several events to Qt (or the app) at the same time on the call stack. This again can easily leave objects in an inconsistent state if they receive callbacks from subsequent events while being occupied processing the first. This is also what happens in the listed report. A QMenu shows a sub menu when the mouse enters a menu item. The show leads to QPA flushing events, which in some cases also includes flushing another pending move event. The move event is delivered to the same QMenu, which will clear a private variable (currentAction). When the show returns, the state of QMenu has unexpectedly changed, which causes a crash to happen since currentAction is null. This patch will fix the root cause of the problem by stopping QCocoaWindow from flushing user input events when the call location does a flush to deliver geometry events. Task-number: QTBUG-66093 Change-Id: Id277550b0a080ad98c81e8c30dc7098dc73723d5 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoawindow.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index af2931c747..683834c1a0 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1131,7 +1131,7 @@ void QCocoaWindow::handleGeometryChange() // Guard against processing window system events during QWindow::setGeometry // calls, which Qt and Qt applications do not expect. if (!m_inSetGeometry) - QWindowSystemInterface::flushWindowSystemEvents(); + QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers); } void QCocoaWindow::handleExposeEvent(const QRegion ®ion) From 41bcb31ab9538328ca05efcb4a01569c9803198c Mon Sep 17 00:00:00 2001 From: Antti Kokko Date: Tue, 30 Jan 2018 15:41:42 +0200 Subject: [PATCH 3/4] Add changes file for Qt 5.10.1 Done-with: Thiago Macieira Done-with: Oswald Buddenhagen Change-Id: I9f3c5a830d210e1224ffbc69979733ec7cf629c6 Reviewed-by: Thiago Macieira --- dist/changes-5.10.1 | 154 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 dist/changes-5.10.1 diff --git a/dist/changes-5.10.1 b/dist/changes-5.10.1 new file mode 100644 index 0000000000..1c9854fa64 --- /dev/null +++ b/dist/changes-5.10.1 @@ -0,0 +1,154 @@ +Qt 5.10.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.10.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +http://doc.qt.io/qt-5/index.html + +The Qt version 5.10 series is binary compatible with the 5.9.x series. +Applications compiled for 5.9 will continue to run with 5.10. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +This release contains all fixes included in the Qt 5.9.4 release. + +**************************************************************************** +* Library * +**************************************************************************** + +QtCore +------ + + - [QTBUG-64529] Fixed a compilation issue with qfloat16 if AVX2 support is + enabled in the compiler. Since all processors that support AVX2 also + support F16C, for GCC and Clang it is recommended to either add -mf16c + to your build or to use the corresponding -march= switch. + + - QCoreApplication: + * [QTBUG-58919] Fixed a crash if QCoreApplication is recreated on Windows + and the passed argv parameter is different. + + - QFile: + * [QTBUG-64103] Fixed a regression in doing rename() on Android + Marshmallow. + + - QFileInfo: + * [QTBUG-30148] Fixed isWritable() on Windows to return whether the given + file is writable only under current privilege levels. Previously, the + result would take into account privilege elevation. + + - QMetaObject: + * [QTBUG-65462] Fixed a memory leak that happened when the new-style + call to invokeMethod() was used. + + - QObject: + * [QTBUG-65712] Improved performance of QObject::deleteLater. + * Fixed a crash that could happen if the context QObject pointer passed to + new-style connect() was null. + + - QPluginLoader: + * [QTBUG-65197] Fixed a bug that would cause the Qt plugin scanning + system to allocate too much memory and possibly crash the process. + + - QProcess: + * [QTBUG-65076] Fixed a regression that made QProcess be unable to find + executables when the PATH environment variable on some Unix systems + wasn't set. This behavior should not be relied upon since many systems + do not have sensible fallback values for PATH. + + - QRandomGenerator: + * [QTBUG-65414] Fixed compilation on Windows if the windows.h header was + included before this qrandom.h. + + - QSettings: + * [QTBUG-64121] Fixed reading from NTFS symbolic links. + + - QStandardPaths: + * [QTBUG-65076] findExecutable() will now apply the default value for + the PATH environment variable (as returned by the POSIX confstr(3) + function or found in ) if the variable isn't set in the + environment. + * [QTBUG-65687] Fixed a memory leak with displayName() on Apple platforms. + * On Windows, it is now possible to resolve configuration paths even + without QCoreApplication created. + + - QString: + * [QTBUG-65939] Fixed a regression from 5.9 that caused comparing + default-constructed QStrings to be sorted after non-empty strings. + + - QTextBoundaryFinder: + * [QTBUG-63191] Fixed a bug in the generating of Unicode data, affecting + the joining properties of characters like U+200C ZWNJ. + + - QXmlStreamWriter: + * [QTBUG-63538] Empty namespace URIs are now possible. + + - State Machine: + * [QTBUG-61463] Fixed a failed assertion that could happen when emitting a + signal from another thread. + +QtGui +----- + + - Text: + * [QTBUG-61882] Fixed a bug where mixing different writing systems with + emojis could lead to missing glyphs. + * [QTBUG-65519] Fixed ZWJ and ZWNJ control characters when fallback + fonts are in use. + +**************************************************************************** +* Platform-specific Changes * +**************************************************************************** + + - QNX: + * [QTBUG-64033] Fixed the detection of slog2 with QNX 7.0 + + - Windows: + * Named pipes internally created by QProcess now contain the PID in their + name to ensure uniqueness. + * [QTBUG-65940] Fixed asserts and crashes in QWinEventNotifier. + + - WinRT: + * -qdevel and -qdebug are removed from the command line arguments and + not passed to the application. + +**************************************************************************** +* Third-Party Code * +**************************************************************************** + + - libjpeg-turbo was updated to version 1.5.3 + +**************************************************************************** +* Tools * +**************************************************************************** + +configure & build system +------------------------ + + - [QTBUG-65753] Fixed installation of resource sources in some examples. + - Qt's pkg-config .pc files now add -DQT_{module}_LIB to CFLAGS. + +qmake +----- + + - [QTBUG-65106] The value of QT is now silently ignored when the sub- + project already failed requires()/REQUIRES. + - [QTBUG-63442] Fixed an issue that would cause warnings with CMake 3.10 + for projects that used AUTOMOC. + - [QTBUG-63637][MinGW] Fixed cross compilation from Linux. + - [QTBUG-65103] Introduced precompile_header_c CONFIG option for MSVC to + enable precompiled header for C sources. + - [QTBUG-65477][Darwin] Added escaping to @BUNDLEIDENTIFIER@. + - [Darwin] Rewrote handling of placeholders in Info.plist; the preferred + style is now ${} and is consistent between Xcode and Makefile generators. + - [Windows] Fixed path separators when setting working directory in + "make check". + - [Windows] Paths which are relative to the current drive's root are not + treated as absolute any more. From 6c6ace9d23f90845fd424e474d38fe30f070775e Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Mon, 8 Jan 2018 15:48:01 +0100 Subject: [PATCH 4/4] psql: Improve performance of record() In order to save having to always run a query to get the tablename for a known oid then we cache the result on the driver side. The oid stays the same while the table exists, so only on dropping it would it change. Recreating the table causes it to get a new oid, so there is no risk of the old one being associated with the wrong table when this happens, if the driver is still open at that point. The benchmark added shows the improvement from the previous code, before the results for PostgreSQL was: RESULT : tst_QSqlRecord::benchmarkRecord():"0_QPSQL@localhost": 259 msecs per iteration (total: 259, iterations: 1) whereas now it is: RESULT : tst_QSqlRecord::benchmarkRecord():"0_QPSQL@localhost": 0.000014 msecs per iteration (total: 59, iterations: 4194304) Task-number: QTBUG-65226 Change-Id: Ic290cff719102743da84e2044cd23e540f20c96c Reviewed-by: Christian Ehrlicher Reviewed-by: Robert Szefner Reviewed-by: Edward Welbourne --- src/plugins/sqldrivers/psql/qsql_psql.cpp | 14 +- .../sql/kernel/qsqlquery/tst_qsqlquery.cpp | 46 ++++- tests/benchmarks/sql/kernel/kernel.pro | 1 + .../sql/kernel/qsqlrecord/qsqlrecord.pro | 5 + .../sql/kernel/qsqlrecord/tst_qsqlrecord.cpp | 191 ++++++++++++++++++ 5 files changed, 252 insertions(+), 5 deletions(-) create mode 100644 tests/benchmarks/sql/kernel/qsqlrecord/qsqlrecord.pro create mode 100644 tests/benchmarks/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp index 35b0f9a3e3..c381572713 100644 --- a/src/plugins/sqldrivers/psql/qsql_psql.cpp +++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp @@ -183,6 +183,7 @@ public: void setDatestyle(); void setByteaOutput(); void detectBackslashEscape(); + mutable QHash oidToTable; }; void QPSQLDriverPrivate::appendTables(QStringList &tl, QSqlQuery &t, QChar type) @@ -553,11 +554,16 @@ QSqlRecord QPSQLResult::record() const f.setName(QString::fromUtf8(PQfname(d->result, i))); else f.setName(QString::fromLocal8Bit(PQfname(d->result, i))); - QSqlQuery qry(driver()->createResult()); - if (qry.exec(QStringLiteral("SELECT relname FROM pg_class WHERE pg_class.oid = %1") - .arg(PQftable(d->result, i))) && qry.next()) { - f.setTableName(qry.value(0).toString()); + const int tableOid = PQftable(d->result, i); + auto &tableName = d->drv_d_func()->oidToTable[tableOid]; + if (tableName.isEmpty()) { + QSqlQuery qry(driver()->createResult()); + if (qry.exec(QStringLiteral("SELECT relname FROM pg_class WHERE pg_class.oid = %1") + .arg(tableOid)) && qry.next()) { + tableName = qry.value(0).toString(); + } } + f.setTableName(tableName); int ptype = PQftype(d->result, i); f.setType(qDecodePSQLType(ptype)); int len = PQfsize(d->result, i); diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp index 1a0340f153..58b87180c8 100644 --- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp @@ -363,7 +363,8 @@ void tst_QSqlQuery::dropTestTables( QSqlDatabase db ) << qTableName("task_234422", __FILE__, db) << qTableName("test141895", __FILE__, db) << qTableName("qtest_oraOCINumber", __FILE__, db) - << qTableName("bug2192", __FILE__, db); + << qTableName("bug2192", __FILE__, db) + << qTableName("tst_record", __FILE__, db); if (dbType == QSqlDriver::PostgreSQL) tablenames << qTableName("task_233829", __FILE__, db); @@ -978,6 +979,29 @@ void tst_QSqlQuery::value() } } +#define SETUP_RECORD_TABLE \ + do { \ + QVERIFY_SQL(q, exec("CREATE TABLE " + tst_record + " (id integer, extra varchar(50))")); \ + for (int i = 0; i < 3; ++i) \ + QVERIFY_SQL(q, exec(QString("INSERT INTO " + tst_record + " VALUES(%1, 'extra%1')").arg(i))); \ + } while (0) + +#define CHECK_RECORD \ + do { \ + QVERIFY_SQL(q, exec(QString("select %1.id, %1.t_varchar, %1.t_char, %2.id, %2.extra from %1, %2 where " \ + "%1.id = %2.id order by %1.id").arg(lowerQTest).arg(tst_record))); \ + QCOMPARE(q.record().fieldName(0).toLower(), QString("id")); \ + QCOMPARE(q.record().field(0).tableName().toLower(), lowerQTest); \ + QCOMPARE(q.record().fieldName(1).toLower(), QString("t_varchar")); \ + QCOMPARE(q.record().field(1).tableName().toLower(), lowerQTest); \ + QCOMPARE(q.record().fieldName(2).toLower(), QString("t_char")); \ + QCOMPARE(q.record().field(2).tableName().toLower(), lowerQTest); \ + QCOMPARE(q.record().fieldName(3).toLower(), QString("id")); \ + QCOMPARE(q.record().field(3).tableName().toLower(), tst_record); \ + QCOMPARE(q.record().fieldName(4).toLower(), QString("extra")); \ + QCOMPARE(q.record().field(4).tableName().toLower(), tst_record); \ + } while (0) + void tst_QSqlQuery::record() { QFETCH( QString, dbName ); @@ -999,6 +1023,26 @@ void tst_QSqlQuery::record() QCOMPARE( q.record().fieldName( 0 ).toLower(), QString( "id" ) ); QCOMPARE( q.value( 0 ).toInt(), 2 ); + + const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db); + if (dbType == QSqlDriver::Oracle) + QSKIP("Getting the tablename is not supported in Oracle"); + const auto lowerQTest = qtest.toLower(); + for (int i = 0; i < 3; ++i) + QCOMPARE(q.record().field(i).tableName().toLower(), lowerQTest); + q.clear(); + const auto tst_record = qTableName("tst_record", __FILE__, db).toLower(); + SETUP_RECORD_TABLE; + CHECK_RECORD; + q.clear(); + + // Recreate the tables, in a different order + const QStringList tables = { qtest, tst_record, qTableName("qtest_null", __FILE__, db) }; + tst_Databases::safeDropTables(db, tables); + SETUP_RECORD_TABLE; + createTestTables(db); + populateTestTables(db); + CHECK_RECORD; } void tst_QSqlQuery::isValid() diff --git a/tests/benchmarks/sql/kernel/kernel.pro b/tests/benchmarks/sql/kernel/kernel.pro index f907feeeac..63887daf5f 100644 --- a/tests/benchmarks/sql/kernel/kernel.pro +++ b/tests/benchmarks/sql/kernel/kernel.pro @@ -1,3 +1,4 @@ TEMPLATE = subdirs SUBDIRS = \ qsqlquery \ + qsqlrecord diff --git a/tests/benchmarks/sql/kernel/qsqlrecord/qsqlrecord.pro b/tests/benchmarks/sql/kernel/qsqlrecord/qsqlrecord.pro new file mode 100644 index 0000000000..840a11bfbe --- /dev/null +++ b/tests/benchmarks/sql/kernel/qsqlrecord/qsqlrecord.pro @@ -0,0 +1,5 @@ +TARGET = tst_bench_qsqlrecord + +SOURCES += tst_qsqlrecord.cpp + +QT = core sql testlib core-private sql-private diff --git a/tests/benchmarks/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp b/tests/benchmarks/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp new file mode 100644 index 0000000000..465dabca0e --- /dev/null +++ b/tests/benchmarks/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp @@ -0,0 +1,191 @@ +/**************************************************************************** + ** + ** Copyright (C) 2018 The Qt Company Ltd. + ** Contact: https://www.qt.io/licensing/ + ** + ** This file is part of the test suite of the Qt Toolkit. + ** + ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ + ** Commercial License Usage + ** Licensees holding valid commercial Qt licenses may use this file in + ** accordance with the commercial license agreement provided with the + ** Software or, alternatively, in accordance with the terms contained in + ** a written agreement between you and The Qt Company. For licensing terms + ** and conditions see https://www.qt.io/terms-conditions. For further + ** information use the contact form at https://www.qt.io/contact-us. + ** + ** GNU General Public License Usage + ** Alternatively, this file may be used under the terms of the GNU + ** General Public License version 3 as published by the Free Software + ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT + ** included in the packaging of this file. Please review the following + ** information to ensure the GNU General Public License requirements will + ** be met: https://www.gnu.org/licenses/gpl-3.0.html. + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#include +#include + +#include "../../../../auto/sql/kernel/qsqldatabase/tst_databases.h" + +const QString qtest(qTableName("qtest", __FILE__, QSqlDatabase())); + +class tst_QSqlRecord : public QObject +{ + Q_OBJECT + +public: + tst_QSqlRecord(); + virtual ~tst_QSqlRecord(); + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void benchmarkRecord_data() { generic_data(); } + void benchmarkRecord(); + +private: + void generic_data(const QString &engine = QString()); + void dropTestTables(QSqlDatabase db); + void createTestTables(QSqlDatabase db); + void populateTestTables(QSqlDatabase db); + + tst_Databases dbs; +}; + +QTEST_MAIN(tst_QSqlRecord) + +tst_QSqlRecord::tst_QSqlRecord() +{ +} + +tst_QSqlRecord::~tst_QSqlRecord() +{ +} + +void tst_QSqlRecord::initTestCase() +{ + dbs.open(); + for (const auto &dbName : qAsConst(dbs.dbNames)) { + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + dropTestTables(db); // In case of leftovers + createTestTables(db); + populateTestTables(db); + } +} + +void tst_QSqlRecord::cleanupTestCase() +{ + for (const auto &dbName : qAsConst(dbs.dbNames)) { + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + dropTestTables(db); + } + dbs.close(); +} + +void tst_QSqlRecord::init() +{ +} + +void tst_QSqlRecord::cleanup() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + const QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db); + + if (QTest::currentTestFailed() && (dbType == QSqlDriver::Oracle || + db.driverName().startsWith("QODBC"))) { + // Since Oracle ODBC has a problem when encountering an error, we init again + db.close(); + db.open(); + } +} + +void tst_QSqlRecord::generic_data(const QString &engine) +{ + if (dbs.fillTestTable(engine) == 0) { + if (engine.isEmpty()) + QSKIP("No database drivers are available in this Qt configuration"); + else + QSKIP(QString("No database drivers of type %1 are available in this Qt configuration").arg(engine).toLocal8Bit()); + } +} + +void tst_QSqlRecord::dropTestTables(QSqlDatabase db) +{ + QSqlDriver::DbmsType dbType = tst_Databases::getDatabaseType(db); + QStringList tablenames; + // drop all the tables in case a testcase failed + tablenames << qtest + << qTableName("record", __FILE__, db); + tst_Databases::safeDropTables(db, tablenames); + + if (dbType == QSqlDriver::Oracle) { + QSqlQuery q(db); + q.exec("DROP PACKAGE " + qTableName("pkg", __FILE__, db)); + } +} + +void tst_QSqlRecord::createTestTables(QSqlDatabase db) +{ + QSqlQuery q(db); + switch (tst_Databases::getDatabaseType(db)) { + case QSqlDriver::PostgreSQL: + QVERIFY_SQL(q, exec("set client_min_messages='warning'")); + QVERIFY_SQL(q, exec("create table " + qtest + " (id serial NOT NULL, t_varchar varchar(20), " + "t_char char(20), primary key(id)) WITH OIDS")); + break; + case QSqlDriver::MySqlServer: + QVERIFY_SQL(q, exec("set table_type=innodb")); + Q_FALLTHROUGH(); + default: + QVERIFY_SQL(q, exec("create table " + qtest + " (id int " + tst_Databases::autoFieldName(db) + + " NOT NULL, t_varchar varchar(20), t_char char(20), primary key(id))")); + break; + } +} + +void tst_QSqlRecord::populateTestTables(QSqlDatabase db) +{ + QSqlQuery q(db); + QVERIFY_SQL(q, exec("delete from " + qtest)); + QVERIFY_SQL(q, exec("insert into " + qtest + " values (1, 'VarChar1', 'Char1')")); + QVERIFY_SQL(q, exec("insert into " + qtest + " values (2, 'VarChar2', 'Char2')")); + QVERIFY_SQL(q, exec("insert into " + qtest + " values (3, 'VarChar3', 'Char3')")); + QVERIFY_SQL(q, exec("insert into " + qtest + " values (4, 'VarChar4', 'Char4')")); + QVERIFY_SQL(q, exec("insert into " + qtest + " values (5, 'VarChar5', 'Char5')")); +} + +void tst_QSqlRecord::benchmarkRecord() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + const auto tableName = qTableName("record", __FILE__, db); + { + QSqlQuery qry(db); + QVERIFY_SQL(qry, exec("create table " + tableName + " (id int NOT NULL, t_varchar varchar(20), " + "t_char char(20), primary key(id))")); + for (int i = 0; i < 1000; i++) + QVERIFY_SQL(qry, exec(QString("INSERT INTO " + tableName + + " VALUES (%1, 'VarChar%1', 'Char%1')").arg(i))); + QVERIFY_SQL(qry, exec(QString("SELECT * from ") + tableName)); + QBENCHMARK { + while (qry.next()) + qry.record(); + } + } + tst_Databases::safeDropTables(db, QStringList() << tableName); +} + +#include "tst_qsqlrecord.moc"