Merge remote-tracking branch 'origin/5.14' into 5.15
Change-Id: I69238f23882deebeaad46e4fdcf899ab22cc2b8f
This commit is contained in:
commit
11d7788c18
@ -1481,6 +1481,10 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
|
|||||||
"type": "error",
|
"type": "error",
|
||||||
"condition": "!features.stl",
|
"condition": "!features.stl",
|
||||||
"message": "Qt requires a compliant STL library."
|
"message": "Qt requires a compliant STL library."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "emccVersion",
|
||||||
|
"condition": "config.wasm"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -1226,6 +1226,12 @@ defineReplace(qtConfOutputPostProcess_publicPro) {
|
|||||||
"QT_RELEASE_DATE = $$config.input.qt_release_date"
|
"QT_RELEASE_DATE = $$config.input.qt_release_date"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wasm: {
|
||||||
|
qt_emcc_version = $$qtSystemEmccVersion()
|
||||||
|
output += \
|
||||||
|
"QT_EMCC_VERSION = $$qt_emcc_version"
|
||||||
|
}
|
||||||
|
|
||||||
return($$output)
|
return($$output)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1258,6 +1264,12 @@ defineReplace(qtConfOutputPostProcess_publicHeader) {
|
|||||||
!isEmpty(config.input.qt_libinfix): \
|
!isEmpty(config.input.qt_libinfix): \
|
||||||
output += "$${LITERAL_HASH}define QT_LIBINFIX \"$$eval(config.input.qt_libinfix)\""
|
output += "$${LITERAL_HASH}define QT_LIBINFIX \"$$eval(config.input.qt_libinfix)\""
|
||||||
|
|
||||||
|
wasm: {
|
||||||
|
qt_emcc_version = $$qtSystemEmccVersion()
|
||||||
|
output += \
|
||||||
|
"$${LITERAL_HASH}define QT_EMCC_VERSION \"$$qt_emcc_version\""
|
||||||
|
}
|
||||||
|
|
||||||
return($$output)
|
return($$output)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1340,6 +1352,14 @@ defineTest(qtConfReport_buildMode) {
|
|||||||
qtConfReportPadded($$1, $$build_mode)
|
qtConfReportPadded($$1, $$build_mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defineTest(qtConfReport_emccVersion) {
|
||||||
|
EMCC_VERSION = $$qtSystemEmccVersion()
|
||||||
|
REQ_VERSION = $$qtEmccRecommendedVersion()
|
||||||
|
!equals(EMCC_VERSION, $$REQ_VERSION) {
|
||||||
|
qtConfAddReport("You should use the recommended Emscripten version $$REQ_VERSION with this Qt. You have $$EMCC_VERSION $$QT_EMCC_VERSION")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# ensure pristine environment for configuration
|
# ensure pristine environment for configuration
|
||||||
discard_from($$[QT_HOST_DATA/get]/mkspecs/qconfig.pri)
|
discard_from($$[QT_HOST_DATA/get]/mkspecs/qconfig.pri)
|
||||||
discard_from($$[QT_HOST_DATA/get]/mkspecs/qmodule.pri)
|
discard_from($$[QT_HOST_DATA/get]/mkspecs/qmodule.pri)
|
||||||
|
@ -6,16 +6,6 @@ isEmpty(QMAKE_MOD_RCC):QMAKE_MOD_RCC = qrc
|
|||||||
!contains(QMAKE_RESOURCE_FLAGS, -root):!isEmpty(QMAKE_RESOURCE_ROOT):QMAKE_RESOURCE_FLAGS += -root $$QMAKE_RESOURCE_ROOT
|
!contains(QMAKE_RESOURCE_FLAGS, -root):!isEmpty(QMAKE_RESOURCE_ROOT):QMAKE_RESOURCE_FLAGS += -root $$QMAKE_RESOURCE_ROOT
|
||||||
!contains(QMAKE_RESOURCE_FLAGS, -name): QMAKE_RESOURCE_FLAGS += -name ${QMAKE_FILE_BASE}
|
!contains(QMAKE_RESOURCE_FLAGS, -name): QMAKE_RESOURCE_FLAGS += -name ${QMAKE_FILE_BASE}
|
||||||
|
|
||||||
# http://www.w3.org/TR/xml/#syntax
|
|
||||||
defineReplace(xml_escape) {
|
|
||||||
1 ~= s,&,&,
|
|
||||||
1 ~= s,\',',
|
|
||||||
1 ~= s,\",",
|
|
||||||
1 ~= s,<,<,
|
|
||||||
1 ~= s,>,>,
|
|
||||||
return($$1)
|
|
||||||
}
|
|
||||||
|
|
||||||
load(resources_functions)
|
load(resources_functions)
|
||||||
qtFlattenResources()
|
qtFlattenResources()
|
||||||
|
|
||||||
|
@ -1,5 +1,21 @@
|
|||||||
|
# http://www.w3.org/TR/xml/#syntax
|
||||||
|
defineReplace(xml_escape) {
|
||||||
|
1 ~= s,&,&,
|
||||||
|
1 ~= s,\',',
|
||||||
|
1 ~= s,\",",
|
||||||
|
1 ~= s,<,<,
|
||||||
|
1 ~= s,>,>,
|
||||||
|
return($$1)
|
||||||
|
}
|
||||||
|
|
||||||
defineTest(qtFlattenResources) {
|
defineTest(qtFlattenResources) {
|
||||||
RESOURCES += qmake_immediate
|
immediate = qmake_immediate$$QMAKE_RESOURCES_IMMEDIATE_NR
|
||||||
|
defined(QMAKE_RESOURCES_IMMEDIATE_NR, var): \
|
||||||
|
QMAKE_RESOURCES_IMMEDIATE_NR = $$num_add($$QMAKE_RESOURCES_IMMEDIATE_NR, 1)
|
||||||
|
else: \
|
||||||
|
QMAKE_RESOURCES_IMMEDIATE_NR = 1
|
||||||
|
|
||||||
|
RESOURCES += $$immediate
|
||||||
for(resource, RESOURCES) {
|
for(resource, RESOURCES) {
|
||||||
# Regular case of user qrc file
|
# Regular case of user qrc file
|
||||||
contains(resource, ".*\\.qrc$"): \
|
contains(resource, ".*\\.qrc$"): \
|
||||||
@ -7,10 +23,10 @@ defineTest(qtFlattenResources) {
|
|||||||
|
|
||||||
# Fallback for stand-alone files/directories
|
# Fallback for stand-alone files/directories
|
||||||
!defined($${resource}.files, var) {
|
!defined($${resource}.files, var) {
|
||||||
!equals(resource, qmake_immediate) {
|
!equals(resource, $$immediate) {
|
||||||
!exists($$absolute_path($$resource, $$_PRO_FILE_PWD_)): \
|
!exists($$absolute_path($$resource, $$_PRO_FILE_PWD_)): \
|
||||||
warning("Failure to find: $$resource")
|
warning("Failure to find: $$resource")
|
||||||
qmake_immediate.files += $$resource
|
$${immediate}.files += $$resource
|
||||||
OTHER_FILES *= $$resource
|
OTHER_FILES *= $$resource
|
||||||
}
|
}
|
||||||
RESOURCES -= $$resource
|
RESOURCES -= $$resource
|
||||||
@ -56,8 +72,9 @@ defineTest(qtFlattenResources) {
|
|||||||
RESOURCES -= $$resource
|
RESOURCES -= $$resource
|
||||||
RESOURCES += $$resource_file
|
RESOURCES += $$resource_file
|
||||||
}
|
}
|
||||||
|
export(QMAKE_RESOURCES_IMMEDIATE_NR)
|
||||||
export(RESOURCES)
|
export(RESOURCES)
|
||||||
export(OTHER_FILES)
|
export(OTHER_FILES)
|
||||||
export(qmake_immediate.files)
|
export($${immediate}.files)
|
||||||
return(true)
|
return(true)
|
||||||
}
|
}
|
||||||
|
25
mkspecs/features/wasm/default_pre.prf
Normal file
25
mkspecs/features/wasm/default_pre.prf
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
load(default_pre)
|
||||||
|
|
||||||
|
defineReplace(qtEmccRecommendedVersion) {
|
||||||
|
return (1.38.27)
|
||||||
|
}
|
||||||
|
|
||||||
|
defineReplace(qtSystemEmccVersion) {
|
||||||
|
E_VERSION = $$system("emcc -v 2>&1 | perl -alne $$shell_quote($_ = $F[9]; s/://; print;) ")
|
||||||
|
return ($${E_VERSION})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineTest(qtConfTest_emccVersion) {
|
||||||
|
|
||||||
|
REQ_VERSION = $$qtEmccRecommendedVersion()
|
||||||
|
EMCC_VERSION = $$qtSystemEmccVersion()
|
||||||
|
|
||||||
|
!defined(QT_EMCC_VERSION, var):!equals(EMCC_VERSION, $${REQ_VERSION}) {
|
||||||
|
warning ("You should use the recommended Emscripten version $$REQ_VERSION with this Qt. You have $${EMCC_VERSION} ")
|
||||||
|
}
|
||||||
|
contains(TEMPLATE, .*app) {
|
||||||
|
!equals(QT_EMCC_VERSION, $$EMCC_VERSION) {
|
||||||
|
warning("This Qt was built with Emscripten version $${QT_EMCC_VERSION}. You have $${EMCC_VERSION}. The difference may cause issues.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,11 @@
|
|||||||
|
|
||||||
|
|
||||||
# DESTDIR will be empty if not set in the app .pro file; make sure it has a value
|
# DESTDIR will be empty if not set in the app .pro file; make sure it has a value
|
||||||
isEmpty(DESTDIR): DESTDIR = $$OUT_PWD
|
isEmpty(DESTDIR): DESTDIR = $$OUT_PWD
|
||||||
|
|
||||||
exists($$QMAKE_QT_CONFIG) {
|
exists($$QMAKE_QT_CONFIG) {
|
||||||
|
## this may be subject to change
|
||||||
|
|
||||||
qtConfig(thread) {
|
qtConfig(thread) {
|
||||||
|
|
||||||
EMCC_THREAD_LFLAGS += -s USE_PTHREADS=1
|
EMCC_THREAD_LFLAGS += -s USE_PTHREADS=1
|
||||||
@ -109,6 +112,8 @@ contains(TEMPLATE, .*app) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qtConfTest_emccVersion()
|
||||||
|
|
||||||
# Pass --source-map-base on the linker line. This informs the
|
# Pass --source-map-base on the linker line. This informs the
|
||||||
# browser where to find the source files when debugging.
|
# browser where to find the source files when debugging.
|
||||||
WASM_SOURCE_MAP_BASE = http://localhost:8000/
|
WASM_SOURCE_MAP_BASE = http://localhost:8000/
|
||||||
|
26
src/3rdparty/sqlite/patches/0001-Fix-CVE-2019-19244-in-SQLite.patch
vendored
Normal file
26
src/3rdparty/sqlite/patches/0001-Fix-CVE-2019-19244-in-SQLite.patch
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
From 676425e522e08eb0e7dfaacdac79a5de27542322 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Andy Shaw <andy.shaw@qt.io>
|
||||||
|
Date: Wed, 11 Dec 2019 10:51:22 +0100
|
||||||
|
Subject: [PATCH 53/53] Fix CVE-2019-19244 in SQLite
|
||||||
|
|
||||||
|
Fixes: QTBUG-80635
|
||||||
|
Change-Id: I718349e28ec76ea164dd50f2a985f2074dd6bdbd
|
||||||
|
---
|
||||||
|
src/3rdparty/sqlite/sqlite3.c | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
|
||||||
|
index 8fd740b300..bd647ca1c2 100644
|
||||||
|
--- a/src/3rdparty/sqlite/sqlite3.c
|
||||||
|
+++ b/src/3rdparty/sqlite/sqlite3.c
|
||||||
|
@@ -131679,6 +131679,7 @@ SQLITE_PRIVATE int sqlite3Select(
|
||||||
|
*/
|
||||||
|
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
|
||||||
|
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
|
||||||
|
+ && p->pWin==0
|
||||||
|
){
|
||||||
|
p->selFlags &= ~SF_Distinct;
|
||||||
|
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
|
||||||
|
--
|
||||||
|
2.21.0 (Apple Git-122.2)
|
||||||
|
|
1
src/3rdparty/sqlite/sqlite3.c
vendored
1
src/3rdparty/sqlite/sqlite3.c
vendored
@ -131679,6 +131679,7 @@ SQLITE_PRIVATE int sqlite3Select(
|
|||||||
*/
|
*/
|
||||||
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
|
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
|
||||||
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
|
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
|
||||||
|
&& p->pWin==0
|
||||||
){
|
){
|
||||||
p->selFlags &= ~SF_Distinct;
|
p->selFlags &= ~SF_Distinct;
|
||||||
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
|
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
|
||||||
|
@ -84,10 +84,10 @@ QT_BEGIN_NAMESPACE
|
|||||||
must start and stop the timer in its thread; it is not possible to
|
must start and stop the timer in its thread; it is not possible to
|
||||||
start a timer from another thread.
|
start a timer from another thread.
|
||||||
|
|
||||||
As a special case, a QTimer with a timeout of 0 will time out as
|
As a special case, a QTimer with a timeout of 0 will time out as soon as
|
||||||
soon as all the events in the window system's event queue have
|
possible, though the ordering between zero timers and other sources of
|
||||||
been processed. This can be used to do heavy work while providing
|
events is unspecified. Zero timers can be used to do some work while still
|
||||||
a snappy user interface:
|
providing a snappy user interface:
|
||||||
|
|
||||||
\snippet timers/timers.cpp 4
|
\snippet timers/timers.cpp 4
|
||||||
\snippet timers/timers.cpp 5
|
\snippet timers/timers.cpp 5
|
||||||
|
@ -4534,15 +4534,24 @@ QSequentialIterable::const_iterator QSequentialIterable::end() const
|
|||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const QVariant variantFromVariantDataHelper(const QtMetaTypePrivate::VariantData &d) {
|
||||||
|
QVariant v;
|
||||||
|
if (d.metaTypeId == qMetaTypeId<QVariant>())
|
||||||
|
v = *reinterpret_cast<const QVariant*>(d.data);
|
||||||
|
else
|
||||||
|
v = QVariant(d.metaTypeId, d.data, d.flags & ~QVariantConstructionFlags::ShouldDeleteVariantData);
|
||||||
|
if (d.flags & QVariantConstructionFlags::ShouldDeleteVariantData)
|
||||||
|
QMetaType::destroy(d.metaTypeId, const_cast<void *>(d.data));
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the element at position \a idx in the container.
|
Returns the element at position \a idx in the container.
|
||||||
*/
|
*/
|
||||||
QVariant QSequentialIterable::at(int idx) const
|
QVariant QSequentialIterable::at(int idx) const
|
||||||
{
|
{
|
||||||
const QtMetaTypePrivate::VariantData d = m_impl.at(idx);
|
const QtMetaTypePrivate::VariantData d = m_impl.at(idx);
|
||||||
if (d.metaTypeId == qMetaTypeId<QVariant>())
|
return variantFromVariantDataHelper(d);
|
||||||
return *reinterpret_cast<const QVariant*>(d.data);
|
|
||||||
return QVariant(d.metaTypeId, d.data, d.flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -4619,9 +4628,7 @@ QSequentialIterable::const_iterator::operator=(const const_iterator &other)
|
|||||||
const QVariant QSequentialIterable::const_iterator::operator*() const
|
const QVariant QSequentialIterable::const_iterator::operator*() const
|
||||||
{
|
{
|
||||||
const QtMetaTypePrivate::VariantData d = m_impl.getCurrent();
|
const QtMetaTypePrivate::VariantData d = m_impl.getCurrent();
|
||||||
if (d.metaTypeId == qMetaTypeId<QVariant>())
|
return variantFromVariantDataHelper(d);
|
||||||
return *reinterpret_cast<const QVariant*>(d.data);
|
|
||||||
return QVariant(d.metaTypeId, d.data, d.flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -4953,10 +4960,7 @@ QAssociativeIterable::const_iterator::operator=(const const_iterator &other)
|
|||||||
const QVariant QAssociativeIterable::const_iterator::operator*() const
|
const QVariant QAssociativeIterable::const_iterator::operator*() const
|
||||||
{
|
{
|
||||||
const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue();
|
const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue();
|
||||||
QVariant v(d.metaTypeId, d.data, d.flags);
|
return variantFromVariantDataHelper(d);
|
||||||
if (d.metaTypeId == qMetaTypeId<QVariant>())
|
|
||||||
return *reinterpret_cast<const QVariant*>(d.data);
|
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -4965,10 +4969,7 @@ const QVariant QAssociativeIterable::const_iterator::operator*() const
|
|||||||
const QVariant QAssociativeIterable::const_iterator::key() const
|
const QVariant QAssociativeIterable::const_iterator::key() const
|
||||||
{
|
{
|
||||||
const QtMetaTypePrivate::VariantData d = m_impl.getCurrentKey();
|
const QtMetaTypePrivate::VariantData d = m_impl.getCurrentKey();
|
||||||
QVariant v(d.metaTypeId, d.data, d.flags);
|
return variantFromVariantDataHelper(d);
|
||||||
if (d.metaTypeId == qMetaTypeId<QVariant>())
|
|
||||||
return *reinterpret_cast<const QVariant*>(d.data);
|
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -4976,11 +4977,7 @@ const QVariant QAssociativeIterable::const_iterator::key() const
|
|||||||
*/
|
*/
|
||||||
const QVariant QAssociativeIterable::const_iterator::value() const
|
const QVariant QAssociativeIterable::const_iterator::value() const
|
||||||
{
|
{
|
||||||
const QtMetaTypePrivate::VariantData d = m_impl.getCurrentValue();
|
return operator*();
|
||||||
QVariant v(d.metaTypeId, d.data, d.flags);
|
|
||||||
if (d.metaTypeId == qMetaTypeId<QVariant>())
|
|
||||||
return *reinterpret_cast<const QVariant*>(d.data);
|
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -105,6 +105,11 @@ inline T *v_cast(QVariant::Private *d, T * = nullptr)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum QVariantConstructionFlags : uint {
|
||||||
|
Default = 0x0,
|
||||||
|
PointerType = 0x1,
|
||||||
|
ShouldDeleteVariantData = 0x2 // only used in Q*Iterable
|
||||||
|
};
|
||||||
|
|
||||||
//a simple template that avoids to allocate 2 memory chunks when creating a QVariant
|
//a simple template that avoids to allocate 2 memory chunks when creating a QVariant
|
||||||
template <class T> class QVariantPrivateSharedEx : public QVariant::PrivateShared
|
template <class T> class QVariantPrivateSharedEx : public QVariant::PrivateShared
|
||||||
|
@ -1626,6 +1626,29 @@ qint64 QDate::daysTo(const QDate &d) const
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if QT_CONFIG(datestring)
|
#if QT_CONFIG(datestring)
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct ParsedInt { int value = 0; bool ok = false; };
|
||||||
|
|
||||||
|
/*
|
||||||
|
/internal
|
||||||
|
|
||||||
|
Read an int that must be the whole text. QStringRef::toInt() will ignore
|
||||||
|
spaces happily; but ISO date format should not.
|
||||||
|
*/
|
||||||
|
ParsedInt readInt(QStringView text)
|
||||||
|
{
|
||||||
|
ParsedInt result;
|
||||||
|
for (const auto &ch : text) {
|
||||||
|
if (ch.isSpace())
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result.value = QLocale::c().toInt(text, &result.ok);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the QDate represented by the \a string, using the
|
Returns the QDate represented by the \a string, using the
|
||||||
\a format given, or an invalid date if the string cannot be
|
\a format given, or an invalid date if the string cannot be
|
||||||
@ -1677,17 +1700,18 @@ QDate QDate::fromString(const QString &string, Qt::DateFormat format)
|
|||||||
return QDate(year, month, day);
|
return QDate(year, month, day);
|
||||||
}
|
}
|
||||||
#endif // textdate
|
#endif // textdate
|
||||||
case Qt::ISODate: {
|
case Qt::ISODate:
|
||||||
// Semi-strict parsing, must be long enough and have non-numeric separators
|
// Semi-strict parsing, must be long enough and have punctuators as separators
|
||||||
if (string.size() < 10 || string.at(4).isDigit() || string.at(7).isDigit()
|
if (string.size() >= 10 && string.at(4).isPunct() && string.at(7).isPunct()
|
||||||
|| (string.size() > 10 && string.at(10).isDigit())) {
|
&& (string.size() == 10 || !string.at(10).isDigit())) {
|
||||||
return QDate();
|
QStringView view(string);
|
||||||
}
|
const ParsedInt year = readInt(view.mid(0, 4));
|
||||||
const int year = string.midRef(0, 4).toInt();
|
const ParsedInt month = readInt(view.mid(5, 2));
|
||||||
if (year <= 0 || year > 9999)
|
const ParsedInt day = readInt(view.mid(8, 2));
|
||||||
return QDate();
|
if (year.ok && year.value > 0 && year.value <= 9999 && month.ok && day.ok)
|
||||||
return QDate(year, string.midRef(5, 2).toInt(), string.midRef(8, 2).toInt());
|
return QDate(year.value, month.value, day.value);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return QDate();
|
return QDate();
|
||||||
}
|
}
|
||||||
@ -2331,17 +2355,15 @@ static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *
|
|||||||
*isMidnight24 = false;
|
*isMidnight24 = false;
|
||||||
|
|
||||||
const int size = string.size();
|
const int size = string.size();
|
||||||
if (size < 5)
|
if (size < 5 || string.at(2) != QLatin1Char(':'))
|
||||||
return QTime();
|
return QTime();
|
||||||
|
|
||||||
const QLocale C(QLocale::c());
|
ParsedInt hour = readInt(string.mid(0, 2));
|
||||||
bool ok = false;
|
ParsedInt minute = readInt(string.mid(3, 2));
|
||||||
int hour = C.toInt(string.mid(0, 2), &ok);
|
if (!hour.ok || !minute.ok)
|
||||||
if (!ok)
|
|
||||||
return QTime();
|
|
||||||
const int minute = C.toInt(string.mid(3, 2), &ok);
|
|
||||||
if (!ok)
|
|
||||||
return QTime();
|
return QTime();
|
||||||
|
// FIXME: ISO 8601 allows [,.]\d+ after hour, just as it does after minute
|
||||||
|
|
||||||
int second = 0;
|
int second = 0;
|
||||||
int msec = 0;
|
int msec = 0;
|
||||||
|
|
||||||
@ -2361,44 +2383,56 @@ static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *
|
|||||||
// will then be rounded up AND clamped to 999.
|
// will then be rounded up AND clamped to 999.
|
||||||
|
|
||||||
const QStringView minuteFractionStr = string.mid(6, qMin(qsizetype(5), string.size() - 6));
|
const QStringView minuteFractionStr = string.mid(6, qMin(qsizetype(5), string.size() - 6));
|
||||||
const long minuteFractionInt = C.toLong(minuteFractionStr, &ok);
|
const ParsedInt parsed = readInt(minuteFractionStr);
|
||||||
if (!ok)
|
if (!parsed.ok)
|
||||||
return QTime();
|
return QTime();
|
||||||
const float minuteFraction = double(minuteFractionInt) / (std::pow(double(10), minuteFractionStr.size()));
|
const float secondWithMs
|
||||||
|
= double(parsed.value) * 60 / (std::pow(double(10), minuteFractionStr.size()));
|
||||||
|
|
||||||
const float secondWithMs = minuteFraction * 60;
|
second = std::floor(secondWithMs);
|
||||||
const float secondNoMs = std::floor(secondWithMs);
|
const float secondFraction = secondWithMs - second;
|
||||||
const float secondFraction = secondWithMs - secondNoMs;
|
|
||||||
second = secondNoMs;
|
|
||||||
msec = qMin(qRound(secondFraction * 1000.0), 999);
|
msec = qMin(qRound(secondFraction * 1000.0), 999);
|
||||||
} else {
|
} else if (string.at(5) == QLatin1Char(':')) {
|
||||||
// HH:mm:ss or HH:mm:ss.zzz
|
// HH:mm:ss or HH:mm:ss.zzz
|
||||||
second = C.toInt(string.mid(6, qMin(qsizetype(2), string.size() - 6)), &ok);
|
const ParsedInt parsed = readInt(string.mid(6, qMin(qsizetype(2), string.size() - 6)));
|
||||||
if (!ok)
|
if (!parsed.ok)
|
||||||
return QTime();
|
return QTime();
|
||||||
if (size > 8 && (string.at(8) == QLatin1Char(',') || string.at(8) == QLatin1Char('.'))) {
|
second = parsed.value;
|
||||||
|
if (size <= 8) {
|
||||||
|
// No fractional part to read
|
||||||
|
} else if (string.at(8) == QLatin1Char(',') || string.at(8) == QLatin1Char('.')) {
|
||||||
QStringView msecStr(string.mid(9, qMin(qsizetype(4), string.size() - 9)));
|
QStringView msecStr(string.mid(9, qMin(qsizetype(4), string.size() - 9)));
|
||||||
// toInt() ignores leading spaces, so catch them before calling it
|
bool ok = true;
|
||||||
|
// Can't use readInt() here, as we *do* allow trailing space - but not leading:
|
||||||
if (!msecStr.isEmpty() && !msecStr.at(0).isDigit())
|
if (!msecStr.isEmpty() && !msecStr.at(0).isDigit())
|
||||||
return QTime();
|
return QTime();
|
||||||
// We do, however, want to ignore *trailing* spaces.
|
|
||||||
msecStr = msecStr.trimmed();
|
msecStr = msecStr.trimmed();
|
||||||
int msecInt = msecStr.isEmpty() ? 0 : C.toInt(msecStr, &ok);
|
int msecInt = msecStr.isEmpty() ? 0 : QLocale::c().toInt(msecStr, &ok);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
return QTime();
|
return QTime();
|
||||||
const double secondFraction(msecInt / (std::pow(double(10), msecStr.size())));
|
const double secondFraction(msecInt / (std::pow(double(10), msecStr.size())));
|
||||||
msec = qMin(qRound(secondFraction * 1000.0), 999);
|
msec = qMin(qRound(secondFraction * 1000.0), 999);
|
||||||
|
} else {
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) // behavior change
|
||||||
|
// Stray cruft after date-time: tolerate trailing space, but nothing else.
|
||||||
|
for (const auto &ch : string.mid(8)) {
|
||||||
|
if (!ch.isSpace())
|
||||||
|
return QTime();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return QTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool isISODate = format == Qt::ISODate || format == Qt::ISODateWithMs;
|
const bool isISODate = format == Qt::ISODate || format == Qt::ISODateWithMs;
|
||||||
if (isISODate && hour == 24 && minute == 0 && second == 0 && msec == 0) {
|
if (isISODate && hour.value == 24 && minute.value == 0 && second == 0 && msec == 0) {
|
||||||
if (isMidnight24)
|
if (isMidnight24)
|
||||||
*isMidnight24 = true;
|
*isMidnight24 = true;
|
||||||
hour = 0;
|
hour.value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return QTime(hour, minute, second, msec);
|
return QTime(hour.value, minute.value, second, msec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Please note that the DB2, Oracle and TDS client drivers are not distributed
|
Please note that the DB2, MySQL, Oracle and TDS client drivers are not
|
||||||
with the Qt Open Source Editions.
|
distributed with the Qt Open Source Editions.
|
||||||
|
|
||||||
This is because the client libraries are distributed under a license which
|
This is because the client libraries are distributed under a license which
|
||||||
is not compatible with the GPL license.
|
is not compatible with the GPL license.
|
||||||
|
@ -692,40 +692,24 @@ QVariant QPSQLResult::data(int i)
|
|||||||
return dbl;
|
return dbl;
|
||||||
}
|
}
|
||||||
case QVariant::Date:
|
case QVariant::Date:
|
||||||
if (val[0] == '\0') {
|
|
||||||
return QVariant(QDate());
|
|
||||||
} else {
|
|
||||||
#if QT_CONFIG(datestring)
|
#if QT_CONFIG(datestring)
|
||||||
return QVariant(QDate::fromString(QString::fromLatin1(val), Qt::ISODate));
|
return QVariant(QDate::fromString(QString::fromLatin1(val), Qt::ISODate));
|
||||||
#else
|
#else
|
||||||
return QVariant(QString::fromLatin1(val));
|
return QVariant(QString::fromLatin1(val));
|
||||||
#endif
|
#endif
|
||||||
}
|
case QVariant::Time:
|
||||||
case QVariant::Time: {
|
|
||||||
const QString str = QString::fromLatin1(val);
|
|
||||||
#if QT_CONFIG(datestring)
|
#if QT_CONFIG(datestring)
|
||||||
if (str.isEmpty())
|
return QVariant(QTime::fromString(QString::fromLatin1(val), Qt::ISODate));
|
||||||
return QVariant(QTime());
|
|
||||||
else
|
|
||||||
return QVariant(QTime::fromString(str, Qt::ISODate));
|
|
||||||
#else
|
#else
|
||||||
return QVariant(str);
|
return QVariant(QString::fromLatin1(val));
|
||||||
#endif
|
#endif
|
||||||
}
|
case QVariant::DateTime:
|
||||||
case QVariant::DateTime: {
|
|
||||||
QString dtval = QString::fromLatin1(val);
|
|
||||||
#if QT_CONFIG(datestring)
|
#if QT_CONFIG(datestring)
|
||||||
if (dtval.length() < 10) {
|
return QVariant(QDateTime::fromString(QString::fromLatin1(val),
|
||||||
return QVariant(QDateTime());
|
Qt::ISODate).toLocalTime());
|
||||||
} else {
|
|
||||||
QChar sign = dtval[dtval.size() - 3];
|
|
||||||
if (sign == QLatin1Char('-') || sign == QLatin1Char('+')) dtval += QLatin1String(":00");
|
|
||||||
return QVariant(QDateTime::fromString(dtval, Qt::ISODate).toLocalTime());
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
return QVariant(dtval);
|
return QVariant(QString::fromLatin1(val));
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
case QVariant::ByteArray: {
|
case QVariant::ByteArray: {
|
||||||
size_t len;
|
size_t len;
|
||||||
unsigned char *data = PQunescapeBytea((const unsigned char*)val, &len);
|
unsigned char *data = PQunescapeBytea((const unsigned char*)val, &len);
|
||||||
|
@ -70,7 +70,6 @@ BEGIN
|
|||||||
END
|
END
|
||||||
//! [1]
|
//! [1]
|
||||||
|
|
||||||
|
|
||||||
//! [3]
|
//! [3]
|
||||||
cd $QTDIR/qtbase/src/plugins/sqldrivers
|
cd $QTDIR/qtbase/src/plugins/sqldrivers
|
||||||
qmake -- MYSQL_PREFIX=/usr/local
|
qmake -- MYSQL_PREFIX=/usr/local
|
||||||
@ -86,14 +85,15 @@ make install
|
|||||||
|
|
||||||
//! [5]
|
//! [5]
|
||||||
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
||||||
qmake -- MYSQL_INCDIR=C:/MySQL/include "MYSQL_LIBDIR=C:/MYSQL/MySQL Server <version>/lib/opt"
|
qmake -- MYSQL_INCDIR="C:/Program Files/MySQL/MySQL Connector C 6.1/include" MYSQL_LIBDIR="C:/Program Files/MySQL/MySQL Connector C 6.1/lib"
|
||||||
nmake sub-mysql
|
nmake sub-mysql
|
||||||
|
nmake install
|
||||||
//! [5]
|
//! [5]
|
||||||
|
|
||||||
|
|
||||||
//! [6]
|
//! [6]
|
||||||
cd $QTDIR/qtbase/src/plugins/sqldrivers
|
cd $QTDIR/qtbase/src/plugins/sqldrivers
|
||||||
qmake -- "OCI_INCDIR=$ORACLE_HOME/rdbms/public" OCI_LIBDIR=$ORACLE_HOME/lib "OCI_LIBS=-lclntsh -lwtc9"
|
qmake -- OCI_INCDIR="$ORACLE_HOME/rdbms/public" OCI_LIBDIR="$ORACLE_HOME/lib" OCI_LIBS="-lclntsh -lwtc9"
|
||||||
make sub-oci
|
make sub-oci
|
||||||
//! [6]
|
//! [6]
|
||||||
|
|
||||||
@ -142,6 +142,7 @@ make sub-psql
|
|||||||
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
||||||
qmake -- PSQL_INCDIR=C:/psql/include PSQL_LIBDIR=C:/psql/lib/ms
|
qmake -- PSQL_INCDIR=C:/psql/include PSQL_LIBDIR=C:/psql/lib/ms
|
||||||
nmake sub-psql
|
nmake sub-psql
|
||||||
|
nmake install
|
||||||
//! [15]
|
//! [15]
|
||||||
|
|
||||||
|
|
||||||
@ -156,6 +157,7 @@ make sub-tds
|
|||||||
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
||||||
qmake
|
qmake
|
||||||
nmake sub-tds
|
nmake sub-tds
|
||||||
|
nmake install
|
||||||
//! [17]
|
//! [17]
|
||||||
|
|
||||||
|
|
||||||
@ -168,8 +170,9 @@ make sub-db2
|
|||||||
|
|
||||||
//! [20]
|
//! [20]
|
||||||
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
||||||
qmake -- "DB2_PREFIX=<DB2 home>/sqllib"
|
qmake -- DB2_PREFIX="<DB2 home>/sqllib"
|
||||||
nmake sub-db2
|
nmake sub-db2
|
||||||
|
nmake install
|
||||||
//! [20]
|
//! [20]
|
||||||
|
|
||||||
|
|
||||||
@ -184,6 +187,7 @@ make sub-sqlite
|
|||||||
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
||||||
qmake -- -system-sqlite SQLITE3_PREFIX=C:/SQLITE
|
qmake -- -system-sqlite SQLITE3_PREFIX=C:/SQLITE
|
||||||
nmake sub-sqlite
|
nmake sub-sqlite
|
||||||
|
nmake install
|
||||||
//! [23]
|
//! [23]
|
||||||
|
|
||||||
|
|
||||||
@ -205,6 +209,7 @@ make sub-ibase
|
|||||||
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
||||||
qmake -- IBASE_INCDIR=C:/interbase/include
|
qmake -- IBASE_INCDIR=C:/interbase/include
|
||||||
nmake sub-ibase
|
nmake sub-ibase
|
||||||
|
nmake install
|
||||||
//! [29]
|
//! [29]
|
||||||
|
|
||||||
|
|
||||||
@ -212,17 +217,18 @@ nmake sub-ibase
|
|||||||
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
cd %QTDIR%\qtbase\src\plugins\sqldrivers
|
||||||
qmake -- IBASE_INCDIR=C:/interbase/include IBASE_LIBS=-lfbclient
|
qmake -- IBASE_INCDIR=C:/interbase/include IBASE_LIBS=-lfbclient
|
||||||
nmake sub-ibase
|
nmake sub-ibase
|
||||||
|
nmake install
|
||||||
//! [30]
|
//! [30]
|
||||||
|
|
||||||
|
|
||||||
//! [32]
|
//! [32]
|
||||||
configure OCI_INCDIR=/usr/include/oracle/10.1.0.3/client OCI_LIBDIR=/usr/lib/oracle/10.1.0.3/client/lib -R /usr/lib/oracle/10.1.0.3/client/lib "OCI_LIBS=-lclntsh -lnnz10"
|
configure OCI_INCDIR=/usr/include/oracle/10.1.0.3/client OCI_LIBDIR=/usr/lib/oracle/10.1.0.3/client/lib -R /usr/lib/oracle/10.1.0.3/client/lib OCI_LIBS="-lclntsh -lnnz10"
|
||||||
make
|
make
|
||||||
//! [32]
|
//! [32]
|
||||||
|
|
||||||
//! [33]
|
//! [33]
|
||||||
cd $QTDIR/qtbase/src/plugins/sqldrivers
|
cd $QTDIR/qtbase/src/plugins/sqldrivers
|
||||||
qmake -- OCI_INCDIR=/usr/include/oracle/10.1.0.3/client OCI_LIBDIR=/usr/lib/oracle/10.1.0.3/client/lib "OCI_LIBS=-Wl,-rpath,/usr/lib/oracle/10.1.0.3/client/lib -lclntsh -lnnz10"
|
qmake -- OCI_INCDIR=/usr/include/oracle/10.1.0.3/client OCI_LIBDIR=/usr/lib/oracle/10.1.0.3/client/lib OCI_LIBS="-Wl,-rpath,/usr/lib/oracle/10.1.0.3/client/lib -lclntsh -lnnz10"
|
||||||
make sub-oci
|
make sub-oci
|
||||||
//! [33]
|
//! [33]
|
||||||
|
|
||||||
@ -250,3 +256,42 @@ q.exec(QString("CREATE TABLE %1 (id INTEGER)").arg(tableString));
|
|||||||
// Call toLower() on the string so that it can be matched
|
// Call toLower() on the string so that it can be matched
|
||||||
QSqlRecord rec = database.record(tableString.toLower());
|
QSqlRecord rec = database.record(tableString.toLower());
|
||||||
//! [40]
|
//! [40]
|
||||||
|
|
||||||
|
//! [41]
|
||||||
|
C:\Qt5\5.13.2\Src\qtbase\src\plugins\sqldrivers>qmake -version
|
||||||
|
QMake version 3.1
|
||||||
|
Using Qt version 5.13.2 in C:/Qt5/5.13.2/mingw73_64/lib
|
||||||
|
C:\Qt5\5.13.2\Src\qtbase\src\plugins\sqldrivers>qmake -- MYSQL_INCDIR="C:/Program Files/MySQL/MySQL Connector C 6.1/include" MYSQL_LIBDIR="C:/Program Files/MySQL/MySQL Connector C 6.1/lib"
|
||||||
|
Info: creating stash file C:\Qt5\5.13.2\Src\qtbase\src\plugins\sqldrivers\.qmake.stash
|
||||||
|
|
||||||
|
Running configuration tests...
|
||||||
|
Checking for DB2 (IBM)... no
|
||||||
|
Checking for InterBase... no
|
||||||
|
Checking for MySQL... yes
|
||||||
|
Checking for OCI (Oracle)... no
|
||||||
|
Checking for ODBC... yes
|
||||||
|
Checking for PostgreSQL... no
|
||||||
|
Checking for SQLite (version 2)... no
|
||||||
|
Checking for TDS (Sybase)... no
|
||||||
|
Done running configuration tests.
|
||||||
|
|
||||||
|
Configure summary:
|
||||||
|
|
||||||
|
Qt Sql Drivers:
|
||||||
|
DB2 (IBM) .............................. no
|
||||||
|
InterBase .............................. no
|
||||||
|
MySql .................................. yes
|
||||||
|
OCI (Oracle) ........................... no
|
||||||
|
ODBC ................................... yes
|
||||||
|
PostgreSQL ............................. no
|
||||||
|
SQLite2 ................................ no
|
||||||
|
SQLite ................................. yes
|
||||||
|
Using system provided SQLite ......... no
|
||||||
|
TDS (Sybase) ........................... no
|
||||||
|
|
||||||
|
Qt is now configured for building. Just run 'mingw32-make'.
|
||||||
|
Once everything is built, you must run 'mingw32-make install'.
|
||||||
|
Qt will be installed into 'C:\Qt5\5.13.2\mingw73_64'.
|
||||||
|
|
||||||
|
Prior to reconfiguration, make sure you remove any leftovers from the previous build.
|
||||||
|
//! [41]
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
\header \li Driver name \li DBMS
|
\header \li Driver name \li DBMS
|
||||||
\row \li \l{#QDB2}{QDB2} \li IBM DB2 (version 7.1 and above)
|
\row \li \l{#QDB2}{QDB2} \li IBM DB2 (version 7.1 and above)
|
||||||
\row \li \l{#QIBASE}{QIBASE} \li Borland InterBase
|
\row \li \l{#QIBASE}{QIBASE} \li Borland InterBase
|
||||||
\row \li \l{#QMYSQL}{QMYSQL} \li MySQL
|
\row \li \l{#QMYSQL}{QMYSQL} \li MySQL (version 5.0 and above)
|
||||||
\row \li \l{#QOCI}{QOCI} \li Oracle Call Interface Driver
|
\row \li \l{#QOCI}{QOCI} \li Oracle Call Interface Driver
|
||||||
\row \li \l{#QODBC}{QODBC}
|
\row \li \l{#QODBC}{QODBC}
|
||||||
\li Open Database Connectivity (ODBC) - Microsoft SQL Server and other
|
\li Open Database Connectivity (ODBC) - Microsoft SQL Server and other
|
||||||
@ -70,7 +70,8 @@
|
|||||||
access to the API exposed by the DBMS, and is typically shipped with it.
|
access to the API exposed by the DBMS, and is typically shipped with it.
|
||||||
Most installation programs also allow you to install "development
|
Most installation programs also allow you to install "development
|
||||||
libraries", and these are what you need. These libraries are responsible
|
libraries", and these are what you need. These libraries are responsible
|
||||||
for the low-level communication with the DBMS.
|
for the low-level communication with the DBMS. Also make sure to install
|
||||||
|
the correct database libraries for your Qt architecture (32 or 64 bit).
|
||||||
|
|
||||||
\note When using Qt under Open Source terms but with a proprietary
|
\note When using Qt under Open Source terms but with a proprietary
|
||||||
database, verify the client library's license compatibility with
|
database, verify the client library's license compatibility with
|
||||||
@ -91,11 +92,21 @@
|
|||||||
may be necessary to specify these paths using the \c *_INCDIR=,
|
may be necessary to specify these paths using the \c *_INCDIR=,
|
||||||
\c *_LIBDIR=, or \c *_PREFIX= command-line options. For example,
|
\c *_LIBDIR=, or \c *_PREFIX= command-line options. For example,
|
||||||
if your MySQL files are installed in \c /usr/local/mysql (or in
|
if your MySQL files are installed in \c /usr/local/mysql (or in
|
||||||
\c{C:\mysql} on Windows), then pass the following parameter to
|
\c{C:/Program Files/MySQL/MySQL Connector C 6.1} on Windows), then pass the
|
||||||
configure: \c MYSQL_PREFIX=/usr/local/mysql
|
following parameter to configure: \c MYSQL_PREFIX=/usr/local/mysql
|
||||||
(or \c{MYSQL_PREFIX=C:\mysql} for Windows).
|
(or \c{MYSQL_PREFIX="C:/Program Files/MySQL/MySQL Connector C 6.1"} for Windows).
|
||||||
The particulars for each driver are explained below.
|
The particulars for each driver are explained below.
|
||||||
|
|
||||||
|
If something goes wrong and you want qmake to recheck your
|
||||||
|
available drivers, you must remove \e{config.cache} in
|
||||||
|
\e{<QTDIR>/qtbase/src/plugins/sqldrivers} - otherwise qmake will not
|
||||||
|
search for the available drivers again. If you encounter an error during
|
||||||
|
the qmake stage, open \e{config.log} to see what went wrong.
|
||||||
|
|
||||||
|
A typical qmake run (in this case to configure for MySQL) looks like this:
|
||||||
|
|
||||||
|
\snippet code/doc_src_sql-driver.qdoc 41
|
||||||
|
|
||||||
Due to the practicalities of dealing with external dependencies,
|
Due to the practicalities of dealing with external dependencies,
|
||||||
only the SQLite3 plugin is shipped with binary builds of Qt.
|
only the SQLite3 plugin is shipped with binary builds of Qt.
|
||||||
To be able to add additional drivers to the Qt installation
|
To be able to add additional drivers to the Qt installation
|
||||||
@ -112,11 +123,11 @@
|
|||||||
\section1 Driver Specifics
|
\section1 Driver Specifics
|
||||||
|
|
||||||
\target QMYSQL
|
\target QMYSQL
|
||||||
\section2 QMYSQL for MySQL 4 and higher
|
\section2 QMYSQL for MySQL 5 and higher
|
||||||
|
|
||||||
\section3 QMYSQL Stored Procedure Support
|
\section3 QMYSQL Stored Procedure Support
|
||||||
|
|
||||||
MySQL 5 introduces stored procedure support at the SQL level, but no
|
MySQL 5 has stored procedure support at the SQL level, but no
|
||||||
API to control IN, OUT, and INOUT parameters. Therefore, parameters
|
API to control IN, OUT, and INOUT parameters. Therefore, parameters
|
||||||
have to be set and read using SQL commands instead of QSqlQuery::bindValue().
|
have to be set and read using SQL commands instead of QSqlQuery::bindValue().
|
||||||
|
|
||||||
@ -159,16 +170,32 @@
|
|||||||
|
|
||||||
\section3 How to Build the QMYSQL Plugin on Windows
|
\section3 How to Build the QMYSQL Plugin on Windows
|
||||||
|
|
||||||
You need to get the MySQL installation files. Run \c SETUP.EXE and
|
You need to get the MySQL installation files (e.g.
|
||||||
choose "Custom Install". Install the "Libs & Include Files" Module.
|
\e{mysql-installer-web-community-8.0.18.0.msi}). Run the installer,
|
||||||
Build the plugin as follows (here it is assumed that MySQL is
|
select custom installation and install the MySQL C Connector
|
||||||
installed in \c{C:\MySQL}):
|
which matches your Qt installation (x86 or x64).
|
||||||
|
After installation make sure that the needed files are there:
|
||||||
|
\list
|
||||||
|
\li \c {<MySQL dir>/lib/libmysql.lib}
|
||||||
|
\li \c {<MySQL dir>/lib/libmysql.dll}
|
||||||
|
\li \c {<MySQL dir>/include/mysql.h}
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
Build the plugin as follows (here it is assumed that the MySQL
|
||||||
|
C Connector is installed in
|
||||||
|
\c{C:/Program Files/MySQL/MySQL Connector C 6.1}):
|
||||||
|
|
||||||
\snippet code/doc_src_sql-driver.qdoc 5
|
\snippet code/doc_src_sql-driver.qdoc 5
|
||||||
|
|
||||||
If you are not using a Microsoft compiler, replace \c nmake with \c
|
If you are not using a Microsoft compiler, replace \c nmake with \c
|
||||||
mingw32-make in the line above.
|
mingw32-make in the line above.
|
||||||
|
|
||||||
|
When you distribute your application, remember to include libmysql.dll
|
||||||
|
in your installation package. It must be placed in the same folder
|
||||||
|
as the application executable. libmysql.dll additionally needs the
|
||||||
|
MSVC runtime libraries which can be installed with vcredist.exe
|
||||||
|
(\l {https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads}(vcredist.exe)
|
||||||
|
|
||||||
\target QOCI
|
\target QOCI
|
||||||
\section2 QOCI for the Oracle Call Interface (OCI)
|
\section2 QOCI for the Oracle Call Interface (OCI)
|
||||||
|
|
||||||
@ -398,11 +425,6 @@
|
|||||||
|
|
||||||
\snippet code/doc_src_sql-driver.qdoc 40
|
\snippet code/doc_src_sql-driver.qdoc 40
|
||||||
|
|
||||||
\section3 QPSQL BLOB Support
|
|
||||||
|
|
||||||
Binary Large Objects are supported through the \c BYTEA field type in
|
|
||||||
PostgreSQL server versions >= 7.1.
|
|
||||||
|
|
||||||
\section3 QPSQL Forward-only query support
|
\section3 QPSQL Forward-only query support
|
||||||
|
|
||||||
To use forward-only queries, you must build the QPSQL plugin with
|
To use forward-only queries, you must build the QPSQL plugin with
|
||||||
@ -463,6 +485,10 @@
|
|||||||
Users of MinGW may wish to consult the following online document:
|
Users of MinGW may wish to consult the following online document:
|
||||||
\l{http://www.postgresql.org/docs/current/static/installation-platform-notes.html#INSTALLATION-NOTES-MINGW}{PostgreSQL MinGW/Native Windows}.
|
\l{http://www.postgresql.org/docs/current/static/installation-platform-notes.html#INSTALLATION-NOTES-MINGW}{PostgreSQL MinGW/Native Windows}.
|
||||||
|
|
||||||
|
When you distribute your application, remember to include libpq.dll
|
||||||
|
in your installation package. It must be placed in the same folder
|
||||||
|
as the application executable.
|
||||||
|
|
||||||
\target QTDS
|
\target QTDS
|
||||||
\section2 QTDS for Sybase Adaptive Server
|
\section2 QTDS for Sybase Adaptive Server
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ template<> inline char *toString(const QByteArray &ba)
|
|||||||
template<> inline char *toString(const QBitArray &ba)
|
template<> inline char *toString(const QBitArray &ba)
|
||||||
{
|
{
|
||||||
qsizetype size = ba.size();
|
qsizetype size = ba.size();
|
||||||
char *str = static_cast<char *>(malloc(size + 1));
|
char *str = new char[size + 1];
|
||||||
for (qsizetype i = 0; i < size; ++i)
|
for (qsizetype i = 0; i < size; ++i)
|
||||||
str[i] = "01"[ba.testBit(i)];
|
str[i] = "01"[ba.testBit(i)];
|
||||||
str[size] = '\0';
|
str[size] = '\0';
|
||||||
|
@ -1717,7 +1717,8 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
|
|||||||
qmlImportScanner += QLatin1String(" -qrcFiles");
|
qmlImportScanner += QLatin1String(" -qrcFiles");
|
||||||
for (const QString &qrcFile : options->qrcFiles)
|
for (const QString &qrcFile : options->qrcFiles)
|
||||||
qmlImportScanner += QLatin1Char(' ') + shellQuote(qrcFile);
|
qmlImportScanner += QLatin1Char(' ') + shellQuote(qrcFile);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
if (rootPath.isEmpty())
|
if (rootPath.isEmpty())
|
||||||
rootPath = QFileInfo(options->inputFileName).absolutePath();
|
rootPath = QFileInfo(options->inputFileName).absolutePath();
|
||||||
else
|
else
|
||||||
@ -1725,8 +1726,8 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
|
|||||||
|
|
||||||
if (!rootPath.endsWith(QLatin1Char('/')))
|
if (!rootPath.endsWith(QLatin1Char('/')))
|
||||||
rootPath += QLatin1Char('/');
|
rootPath += QLatin1Char('/');
|
||||||
|
|
||||||
qmlImportScanner += QLatin1String(" -rootPath %1").arg(shellQuote(rootPath));
|
qmlImportScanner += QLatin1String(" -rootPath %1").arg(shellQuote(rootPath));
|
||||||
}
|
|
||||||
|
|
||||||
QStringList importPaths;
|
QStringList importPaths;
|
||||||
importPaths += shellQuote(options->qtInstallDirectory + QLatin1String("/qml"));
|
importPaths += shellQuote(options->qtInstallDirectory + QLatin1String("/qml"));
|
||||||
|
@ -1478,12 +1478,18 @@ bool RCCResourceLibrary::writeInitializer()
|
|||||||
writeString(" return 1;\n");
|
writeString(" return 1;\n");
|
||||||
writeString("}\n\n");
|
writeString("}\n\n");
|
||||||
|
|
||||||
writeByteArray(
|
|
||||||
"namespace {\n"
|
writeString("namespace {\n"
|
||||||
" struct initializer {\n"
|
" struct initializer {\n");
|
||||||
" initializer() { QT_RCC_MANGLE_NAMESPACE(" + initResources + ")(); }\n"
|
|
||||||
" ~initializer() { QT_RCC_MANGLE_NAMESPACE(" + cleanResources + ")(); }\n"
|
if (m_useNameSpace) {
|
||||||
" } dummy;\n"
|
writeByteArray(" initializer() { QT_RCC_MANGLE_NAMESPACE(" + initResources + ")(); }\n"
|
||||||
|
" ~initializer() { QT_RCC_MANGLE_NAMESPACE(" + cleanResources + ")(); }\n");
|
||||||
|
} else {
|
||||||
|
writeByteArray(" initializer() { " + initResources + "(); }\n"
|
||||||
|
" ~initializer() { " + cleanResources + "(); }\n");
|
||||||
|
}
|
||||||
|
writeString(" } dummy;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
|
|
||||||
} else if (m_format == Binary) {
|
} else if (m_format == Binary) {
|
||||||
|
@ -146,13 +146,13 @@ dialog.exec();
|
|||||||
//! [14]
|
//! [14]
|
||||||
|
|
||||||
//! [15]
|
//! [15]
|
||||||
auto fileOpenCompleted = [](const QString &fileName, const QByteArray &fileContent) {
|
auto fileContentReady = [](const QString &fileName, const QByteArray &fileContent) {
|
||||||
if (fileName.isEmpty()) {
|
if (fileName.isEmpty()) {
|
||||||
// No file was selected
|
// No file was selected
|
||||||
} else {
|
} else {
|
||||||
// Use fileName and fileContent
|
// Use fileName and fileContent
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
QFileDialog::getOpenFileContent("Images (*.png *.xpm *.jpg)", fileContentReady);
|
QFileDialog::getOpenFileContent("Images (*.png *.xpm *.jpg)", fileContentReady);
|
||||||
//! [15]
|
//! [15]
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include <QtTest/QtTest>
|
#include <QtTest/QtTest>
|
||||||
|
|
||||||
#include <qvariant.h>
|
#include <qvariant.h>
|
||||||
|
#include <QtCore/private/qvariant_p.h>
|
||||||
#include <qbitarray.h>
|
#include <qbitarray.h>
|
||||||
#include <qbytearraylist.h>
|
#include <qbytearraylist.h>
|
||||||
#include <qdatetime.h>
|
#include <qdatetime.h>
|
||||||
@ -276,7 +277,8 @@ private slots:
|
|||||||
void nullConvert();
|
void nullConvert();
|
||||||
|
|
||||||
void accessSequentialContainerKey();
|
void accessSequentialContainerKey();
|
||||||
|
void shouldDeleteVariantDataWorksForSequential();
|
||||||
|
void shouldDeleteVariantDataWorksForAssociative();
|
||||||
void fromStdVariant();
|
void fromStdVariant();
|
||||||
void qt4UuidDataStream();
|
void qt4UuidDataStream();
|
||||||
|
|
||||||
@ -4990,6 +4992,99 @@ void tst_QVariant::accessSequentialContainerKey()
|
|||||||
QCOMPARE(nameResult, QStringLiteral("Seven"));
|
QCOMPARE(nameResult, QStringLiteral("Seven"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QVariant::shouldDeleteVariantDataWorksForSequential()
|
||||||
|
{
|
||||||
|
QCOMPARE(instanceCount, 0);
|
||||||
|
{
|
||||||
|
QtMetaTypePrivate::QSequentialIterableImpl iterator {};
|
||||||
|
iterator._iteratorCapabilities = QtMetaTypePrivate::RandomAccessCapability |
|
||||||
|
QtMetaTypePrivate::BiDirectionalCapability |
|
||||||
|
QtMetaTypePrivate::ForwardCapability;
|
||||||
|
iterator._metaType_flags = QVariantConstructionFlags::ShouldDeleteVariantData;
|
||||||
|
|
||||||
|
iterator._size = [](const void *) {return 1;};
|
||||||
|
iterator._metaType_id = qMetaTypeId<MyType>();
|
||||||
|
iterator._moveToBegin = [](const void *, void **) {};
|
||||||
|
iterator._moveToEnd = [](const void *, void **) {};
|
||||||
|
iterator._advance = [](void **, int) {};
|
||||||
|
iterator._destroyIter = [](void **){};
|
||||||
|
iterator._equalIter = [](void * const *, void * const *){return true; /*all iterators are nullptr*/};
|
||||||
|
iterator._destroyIter = [](void **){};
|
||||||
|
iterator._at = [](const void *, int ) -> void const * {
|
||||||
|
MyType mytype {1, "eins"};
|
||||||
|
return QMetaType::create(qMetaTypeId<MyType>(), &mytype);
|
||||||
|
};
|
||||||
|
iterator._get = [](void * const *, int, uint) -> QtMetaTypePrivate::VariantData {
|
||||||
|
MyType mytype {2, "zwei"};
|
||||||
|
return {qMetaTypeId<MyType>(), QMetaType::create(qMetaTypeId<MyType>(), &mytype), QVariantConstructionFlags::ShouldDeleteVariantData};
|
||||||
|
};
|
||||||
|
QSequentialIterable iterable {iterator};
|
||||||
|
QVariant value1 = iterable.at(0);
|
||||||
|
QVERIFY(value1.canConvert<MyType>());
|
||||||
|
QCOMPARE(value1.value<MyType>().number, 1);
|
||||||
|
QVariant value2 = *iterable.begin();
|
||||||
|
QVERIFY(value2.canConvert<MyType>());
|
||||||
|
QCOMPARE(value2.value<MyType>().number, 2);
|
||||||
|
}
|
||||||
|
QCOMPARE(instanceCount, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QVariant::shouldDeleteVariantDataWorksForAssociative()
|
||||||
|
{
|
||||||
|
QCOMPARE(instanceCount, 0);
|
||||||
|
{
|
||||||
|
QtMetaTypePrivate::QAssociativeIterableImpl iterator {};
|
||||||
|
iterator._metaType_flags_key = QVariantConstructionFlags::ShouldDeleteVariantData;
|
||||||
|
iterator._metaType_flags_value = QVariantConstructionFlags::ShouldDeleteVariantData;
|
||||||
|
|
||||||
|
iterator._size = [](const void *) {return 1;};
|
||||||
|
iterator._metaType_id_value = qMetaTypeId<MyType>();
|
||||||
|
iterator._metaType_id_key = qMetaTypeId<MyType>();
|
||||||
|
iterator._begin = [](const void *, void **) {};
|
||||||
|
iterator._end = [](const void *, void **) {};
|
||||||
|
iterator._advance = [](void **, int) {};
|
||||||
|
iterator._destroyIter = [](void **){};
|
||||||
|
iterator._equalIter = [](void * const *, void * const *){return true; /*all iterators are nullptr*/};
|
||||||
|
iterator._destroyIter = [](void **){};
|
||||||
|
iterator._find = [](const void *, const void *, void **iterator ) -> void {
|
||||||
|
(*iterator) = reinterpret_cast<void *>(quintptr(42));
|
||||||
|
};
|
||||||
|
iterator._getKey = [](void * const *iterator, int, uint) -> QtMetaTypePrivate::VariantData {
|
||||||
|
MyType mytype {1, "key"};
|
||||||
|
if (reinterpret_cast<quintptr>(*iterator) == 42) {
|
||||||
|
mytype.number = 42;
|
||||||
|
mytype.text = "find_key";
|
||||||
|
}
|
||||||
|
return {qMetaTypeId<MyType>(), QMetaType::create(qMetaTypeId<MyType>(), &mytype), QVariantConstructionFlags::ShouldDeleteVariantData};
|
||||||
|
};
|
||||||
|
iterator._getValue = [](void * const *iterator, int, uint) -> QtMetaTypePrivate::VariantData {
|
||||||
|
MyType mytype {2, "value"};
|
||||||
|
if (reinterpret_cast<quintptr>(*iterator) == 42) {
|
||||||
|
mytype.number = 42;
|
||||||
|
mytype.text = "find_value";
|
||||||
|
}
|
||||||
|
return {qMetaTypeId<MyType>(), QMetaType::create(qMetaTypeId<MyType>(), &mytype), QVariantConstructionFlags::ShouldDeleteVariantData};
|
||||||
|
};
|
||||||
|
QAssociativeIterable iterable {iterator};
|
||||||
|
auto it = iterable.begin();
|
||||||
|
QVariant value1 = it.key();
|
||||||
|
QVERIFY(value1.canConvert<MyType>());
|
||||||
|
QCOMPARE(value1.value<MyType>().number, 1);
|
||||||
|
QCOMPARE(value1.value<MyType>().text, "key");
|
||||||
|
QVariant value2 = it.value();
|
||||||
|
QVERIFY(value2.canConvert<MyType>());
|
||||||
|
QCOMPARE(value2.value<MyType>().number, 2);
|
||||||
|
auto findIt = iterable.find(QVariant::fromValue(MyType {}));
|
||||||
|
value1 = findIt.key();
|
||||||
|
QCOMPARE(value1.value<MyType>().number, 42);
|
||||||
|
QCOMPARE(value1.value<MyType>().text, "find_key");
|
||||||
|
value2 = findIt.value();
|
||||||
|
QCOMPARE(value2.value<MyType>().number, 42);
|
||||||
|
QCOMPARE(value2.value<MyType>().text, "find_value");
|
||||||
|
}
|
||||||
|
QCOMPARE(instanceCount, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QVariant::fromStdVariant()
|
void tst_QVariant::fromStdVariant()
|
||||||
{
|
{
|
||||||
#if __has_include(<variant>) && __cplusplus >= 201703L
|
#if __has_include(<variant>) && __cplusplus >= 201703L
|
||||||
|
@ -2213,8 +2213,46 @@ void tst_QDateTime::fromStringDateFormat_data()
|
|||||||
QTest::newRow("trailing space") // QTBUG-80445
|
QTest::newRow("trailing space") // QTBUG-80445
|
||||||
<< QString("2000-01-02 03:04:05.678 ")
|
<< QString("2000-01-02 03:04:05.678 ")
|
||||||
<< Qt::ISODate << QDateTime(QDate(2000, 1, 2), QTime(3, 4, 5, 678));
|
<< Qt::ISODate << QDateTime(QDate(2000, 1, 2), QTime(3, 4, 5, 678));
|
||||||
|
|
||||||
|
// Invalid spaces (but keeping field widths correct):
|
||||||
QTest::newRow("space before millis")
|
QTest::newRow("space before millis")
|
||||||
<< QString("2000-01-02 03:04:05. 678") << Qt::ISODate << QDateTime();
|
<< QString("2000-01-02 03:04:05. 678") << Qt::ISODate << QDateTime();
|
||||||
|
QTest::newRow("space after seconds")
|
||||||
|
<< QString("2000-01-02 03:04:5 .678") << Qt::ISODate << QDateTime();
|
||||||
|
QTest::newRow("space before seconds")
|
||||||
|
<< QString("2000-01-02 03:04: 5.678") << Qt::ISODate << QDateTime();
|
||||||
|
QTest::newRow("space after minutes")
|
||||||
|
<< QString("2000-01-02 03:4 :05.678") << Qt::ISODate << QDateTime();
|
||||||
|
QTest::newRow("space before minutes")
|
||||||
|
<< QString("2000-01-02 03: 4:05.678") << Qt::ISODate << QDateTime();
|
||||||
|
QTest::newRow("space after hour")
|
||||||
|
<< QString("2000-01-02 3 :04:05.678") << Qt::ISODate << QDateTime();
|
||||||
|
QTest::newRow("space before hour")
|
||||||
|
<< QString("2000-01-02 3:04:05.678") << Qt::ISODate << QDateTime();
|
||||||
|
QTest::newRow("space after day")
|
||||||
|
<< QString("2000-01-2 03:04:05.678") << Qt::ISODate << QDateTime();
|
||||||
|
QTest::newRow("space before day")
|
||||||
|
<< QString("2000-01- 2 03:04:05.678") << Qt::ISODate << QDateTime();
|
||||||
|
QTest::newRow("space after month")
|
||||||
|
<< QString("2000-1 -02 03:04:05.678") << Qt::ISODate << QDateTime();
|
||||||
|
QTest::newRow("space before month")
|
||||||
|
<< QString("2000- 1-02 03:04:05.678") << Qt::ISODate << QDateTime();
|
||||||
|
QTest::newRow("space after year")
|
||||||
|
<< QString("200 -01-02 03:04:05.678") << Qt::ISODate << QDateTime();
|
||||||
|
|
||||||
|
// Spaces as separators:
|
||||||
|
QTest::newRow("sec-milli space")
|
||||||
|
<< QString("2000-01-02 03:04:05 678") << Qt::ISODate
|
||||||
|
// Should be invalid, but we ignore trailing cruft (in some cases)
|
||||||
|
<< QDateTime(QDate(2000, 1, 2), QTime(3, 4, 5));
|
||||||
|
QTest::newRow("min-sec space")
|
||||||
|
<< QString("2000-01-02 03:04 05.678") << Qt::ISODate << QDateTime();
|
||||||
|
QTest::newRow("hour-min space")
|
||||||
|
<< QString("2000-01-02 03 04:05.678") << Qt::ISODate << QDateTime();
|
||||||
|
QTest::newRow("mon-day space")
|
||||||
|
<< QString("2000-01 02 03:04:05.678") << Qt::ISODate << QDateTime();
|
||||||
|
QTest::newRow("year-mon space")
|
||||||
|
<< QString("2000 01-02 03:04:05.678") << Qt::ISODate << QDateTime();
|
||||||
|
|
||||||
// Normal usage:
|
// Normal usage:
|
||||||
QTest::newRow("ISO +01:00") << QString::fromLatin1("1987-02-13T13:24:51+01:00")
|
QTest::newRow("ISO +01:00") << QString::fromLatin1("1987-02-13T13:24:51+01:00")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user