From 598be12d4a84f7167ae61a120588f8ceea55c556 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Wed, 8 Feb 2023 19:06:46 +0100 Subject: SQL/MySQL: Fix retrieving a datetime for libmysql >= 8.0.27 Somewhere between libmysql 8.0.18 and 8.0.27, the MYSQL_TIME structure gained an additional member which increased the struct size by 4 bytes. This makes an internal check for the correct size of the structi go fail. Since it can now happen that the plugin is linked against a new libmysql and used with an old and the other way round, duplicate the old MYSQL_TIME struct to use this in our code Fixes: QTBUG-110967 Change-Id: I5bc631179a0a1be47a5966954e757f27a72f1592 Reviewed-by: Thiago Macieira (cherry picked from commit c67cc6d5706fa732ee78e286e0142f97f5b9d61f) Reviewed-by: Qt Cherry-pick Bot --- src/plugins/sqldrivers/mysql/qsql_mysql.cpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp index df0d19229a..3b954dfcbd 100644 --- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp +++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp @@ -33,6 +33,17 @@ Q_DECLARE_METATYPE(MYSQL_STMT*) // by redefining it we can regain source compatibility. using my_bool = decltype(mysql_stmt_bind_result(nullptr, nullptr)); +// this is a copy of the old MYSQL_TIME before an additional integer was added in +// 8.0.27.0. This kills the sanity check during retrieving this struct from mysql +// when another libmysql version is used during runtime than during compile time +struct QT_MYSQL_TIME +{ + unsigned int year, month, day, hour, minute, second; + unsigned long second_part; /**< microseconds */ + my_bool neg; + enum enum_mysql_timestamp_type time_type; +}; + QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; @@ -330,7 +341,7 @@ bool QMYSQLResultPrivate::bindInValues() bind->buffer_length = f.bufLength = 0; hasBlobs = true; } else if (qIsTimeOrDate(fieldInfo->type)) { - bind->buffer_length = f.bufLength = sizeof(MYSQL_TIME); + bind->buffer_length = f.bufLength = sizeof(QT_MYSQL_TIME); } else if (qIsInteger(f.type.id())) { bind->buffer_length = f.bufLength = 8; } else { @@ -534,8 +545,8 @@ QVariant QMYSQLResult::data(int field) else if (f.type.id() == QMetaType::Char) return variant.toInt(); return variant; - } else if (qIsTimeOrDate(f.myField->type) && f.bufLength == sizeof(MYSQL_TIME)) { - auto t = reinterpret_cast(f.outField); + } else if (qIsTimeOrDate(f.myField->type) && f.bufLength >= sizeof(QT_MYSQL_TIME)) { + auto t = reinterpret_cast(f.outField); QDate date; QTime time; if (f.type.id() != QMetaType::QTime) @@ -795,13 +806,12 @@ void QMYSQLResult::virtual_hook(int id, void *data) QSqlResult::virtual_hook(id, data); } -static MYSQL_TIME *toMySqlDate(QDate date, QTime time, int type) +static QT_MYSQL_TIME *toMySqlDate(QDate date, QTime time, int type) { Q_ASSERT(type == QMetaType::QTime || type == QMetaType::QDate || type == QMetaType::QDateTime); - MYSQL_TIME *myTime = new MYSQL_TIME; - memset(myTime, 0, sizeof(MYSQL_TIME)); + auto myTime = new QT_MYSQL_TIME{}; if (type == QMetaType::QTime || type == QMetaType::QDateTime) { myTime->hour = time.hour(); @@ -870,7 +880,7 @@ bool QMYSQLResult::exec() return false; int r = 0; - QList timeVector; + QList timeVector; QList stringVector; QList nullVector; @@ -908,7 +918,7 @@ bool QMYSQLResult::exec() case QMetaType::QTime: case QMetaType::QDate: case QMetaType::QDateTime: { - MYSQL_TIME *myTime = toMySqlDate(val.toDate(), val.toTime(), val.userType()); + QT_MYSQL_TIME *myTime = toMySqlDate(val.toDate(), val.toTime(), val.userType()); timeVector.append(myTime); currBind->buffer = myTime; @@ -928,7 +938,7 @@ bool QMYSQLResult::exec() default: break; } - currBind->buffer_length = sizeof(MYSQL_TIME); + currBind->buffer_length = sizeof(QT_MYSQL_TIME); currBind->length = 0; break; } case QMetaType::UInt: -- cgit v1.2.1