Merge remote-tracking branch 'origin/5.10.1' into 5.11

Conflicts:
	src/plugins/sqldrivers/psql/qsql_psql.cpp

Change-Id: I070b455078b41e75c46562fcea5676d6218cd00c
This commit is contained in:
Liang Qi 2018-02-19 14:56:24 +01:00
commit 48577b2e7f
9 changed files with 411 additions and 16 deletions

154
dist/changes-5.10.1 vendored Normal file
View File

@ -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 <paths.h>) 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.

View File

@ -568,10 +568,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)
@ -600,11 +596,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);

View File

@ -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 &region)

View File

@ -204,6 +204,7 @@ public:
void setDatestyle();
void setByteaOutput();
void detectBackslashEscape();
mutable QHash<int, QString> oidToTable;
};
void QPSQLDriverPrivate::appendTables(QStringList &tl, QSqlQuery &t, QChar type)
@ -815,18 +816,20 @@ QSqlRecord QPSQLResult::record() const
f.setName(QString::fromUtf8(PQfname(d->result, i)));
else
f.setName(QString::fromLocal8Bit(PQfname(d->result, i)));
const int tableOid = PQftable(d->result, i);
auto &tableName = d->drv_d_func()->oidToTable[tableOid];
// WARNING: We cannot execute any other SQL queries on
// the same db connection while forward-only mode is active
// (this would discard all results of forward-only query).
// So we just skip this...
if (!isForwardOnly()) {
if (tableName.isEmpty() && !isForwardOnly()) {
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());
.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);

View File

@ -6049,8 +6049,14 @@ void tst_QString::compare_data()
QTest::addColumn<int>("csr"); // case sensitive result
QTest::addColumn<int>("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;

View File

@ -370,7 +370,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);
@ -1009,6 +1010,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 );
@ -1030,6 +1054,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()

View File

@ -1,3 +1,4 @@
TEMPLATE = subdirs
SUBDIRS = \
qsqlquery \
qsqlrecord

View File

@ -0,0 +1,5 @@
TARGET = tst_bench_qsqlrecord
SOURCES += tst_qsqlrecord.cpp
QT = core sql testlib core-private sql-private

View File

@ -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 <QtTest/QtTest>
#include <QtSql/QtSql>
#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"