@@ -29,10 +29,26 @@ Q_DECLARE_METATYPE(MYSQL_RES*)
2929Q_DECLARE_METATYPE(MYSQL*)
3030Q_DECLARE_METATYPE(MYSQL_STMT*)
3131
32+ // MYSQL_TYPE_JSON was introduced with MySQL 5.7.9
33+ #if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID < 50709
34+ #define MYSQL_TYPE_JSON 245
35+ #endif
36+
3237// MySQL above version 8 removed my_bool typedef while MariaDB kept it,
3338// by redefining it we can regain source compatibility.
3439using my_bool = decltype (mysql_stmt_bind_result(nullptr , nullptr ));
3540
41+ // this is a copy of the old MYSQL_TIME before an additional integer was added in
42+ // 8.0.27.0. This kills the sanity check during retrieving this struct from mysql
43+ // when another libmysql version is used during runtime than during compile time
44+ struct QT_MYSQL_TIME
45+ {
46+ unsigned int year, month, day, hour, minute, second;
47+ unsigned long second_part; /* *< microseconds */
48+ my_bool neg;
49+ enum enum_mysql_timestamp_type time_type;
50+ };
51+
3652QT_BEGIN_NAMESPACE
3753
3854using namespace Qt ::StringLiterals;
@@ -80,7 +96,7 @@ static inline QVariant qDateTimeFromString(QString &val)
8096#else
8197 if (val.isEmpty ())
8298 return QVariant (QDateTime ());
83- if (val.length () == 14 )
99+ if (val.size () == 14 )
84100 // TIMESTAMPS have the format yyyyMMddhhmmss
85101 val.insert (4 , u' -' ).insert (7 , u' -' ).insert (10 , u' T' ).insert (13 , u' :' ).insert (16 , u' :' );
86102 return QVariant (QDateTime::fromString (val, Qt::ISODate));
@@ -181,58 +197,59 @@ static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type,
181197}
182198
183199
184- static QMetaType qDecodeMYSQLType (int mysqltype, uint flags)
200+ static QMetaType qDecodeMYSQLType (enum_field_types mysqltype, uint flags)
185201{
186202 QMetaType::Type type;
187203 switch (mysqltype) {
188- case FIELD_TYPE_TINY :
204+ case MYSQL_TYPE_TINY :
189205 type = (flags & UNSIGNED_FLAG) ? QMetaType::UChar : QMetaType::Char;
190206 break ;
191- case FIELD_TYPE_SHORT :
207+ case MYSQL_TYPE_SHORT :
192208 type = (flags & UNSIGNED_FLAG) ? QMetaType::UShort : QMetaType::Short;
193209 break ;
194- case FIELD_TYPE_LONG :
195- case FIELD_TYPE_INT24 :
210+ case MYSQL_TYPE_LONG :
211+ case MYSQL_TYPE_INT24 :
196212 type = (flags & UNSIGNED_FLAG) ? QMetaType::UInt : QMetaType::Int;
197213 break ;
198- case FIELD_TYPE_YEAR :
214+ case MYSQL_TYPE_YEAR :
199215 type = QMetaType::Int;
200216 break ;
201- case FIELD_TYPE_LONGLONG :
217+ case MYSQL_TYPE_LONGLONG :
202218 type = (flags & UNSIGNED_FLAG) ? QMetaType::ULongLong : QMetaType::LongLong;
203219 break ;
204- case FIELD_TYPE_FLOAT :
205- case FIELD_TYPE_DOUBLE :
206- case FIELD_TYPE_DECIMAL :
207- #if defined(FIELD_TYPE_NEWDECIMAL)
208- case FIELD_TYPE_NEWDECIMAL:
209- #endif
220+ case MYSQL_TYPE_FLOAT:
221+ case MYSQL_TYPE_DOUBLE:
222+ case MYSQL_TYPE_DECIMAL:
223+ case MYSQL_TYPE_NEWDECIMAL:
210224 type = QMetaType::Double;
211225 break ;
212- case FIELD_TYPE_DATE :
226+ case MYSQL_TYPE_DATE :
213227 type = QMetaType::QDate;
214228 break ;
215- case FIELD_TYPE_TIME :
229+ case MYSQL_TYPE_TIME :
216230 // A time field can be within the range '-838:59:59' to '838:59:59' so
217231 // use QString instead of QTime since QTime is limited to 24 hour clock
218232 type = QMetaType::QString;
219233 break ;
220- case FIELD_TYPE_DATETIME :
221- case FIELD_TYPE_TIMESTAMP :
234+ case MYSQL_TYPE_DATETIME :
235+ case MYSQL_TYPE_TIMESTAMP :
222236 type = QMetaType::QDateTime;
223237 break ;
224- case FIELD_TYPE_STRING :
225- case FIELD_TYPE_VAR_STRING :
226- case FIELD_TYPE_BLOB :
227- case FIELD_TYPE_TINY_BLOB :
228- case FIELD_TYPE_MEDIUM_BLOB :
229- case FIELD_TYPE_LONG_BLOB :
230- case FIELD_TYPE_GEOMETRY :
238+ case MYSQL_TYPE_STRING:
239+ case MYSQL_TYPE_VAR_STRING:
240+ case MYSQL_TYPE_BLOB:
241+ case MYSQL_TYPE_TINY_BLOB:
242+ case MYSQL_TYPE_MEDIUM_BLOB:
243+ case MYSQL_TYPE_LONG_BLOB:
244+ case MYSQL_TYPE_GEOMETRY:
245+ case MYSQL_TYPE_JSON:
231246 type = (flags & BINARY_FLAG) ? QMetaType::QByteArray : QMetaType::QString;
232247 break ;
233- default :
234- case FIELD_TYPE_ENUM :
235- case FIELD_TYPE_SET :
248+ case MYSQL_TYPE_ENUM:
249+ case MYSQL_TYPE_SET:
250+ type = QMetaType::QString;
251+ break ;
252+ default : // needed because there are more enum values which are not available in all headers
236253 type = QMetaType::QString;
237254 break ;
238255 }
@@ -242,7 +259,7 @@ static QMetaType qDecodeMYSQLType(int mysqltype, uint flags)
242259static QSqlField qToField (MYSQL_FIELD *field)
243260{
244261 QSqlField f (QString::fromUtf8 (field->name ),
245- qDecodeMYSQLType (int ( field->type ) , field->flags ),
262+ qDecodeMYSQLType (field->type , field->flags ),
246263 QString::fromUtf8 (field->table ));
247264 f.setRequired (IS_NOT_NULL (field->flags ));
248265 f.setLength (field->length );
@@ -261,15 +278,16 @@ static QSqlError qMakeStmtError(const QString& err, QSqlError::ErrorType type,
261278 type, QString::number (mysql_stmt_errno (stmt)));
262279}
263280
264- static bool qIsBlob (int t)
281+ static bool qIsBlob (enum_field_types t)
265282{
266283 return t == MYSQL_TYPE_TINY_BLOB
267284 || t == MYSQL_TYPE_BLOB
268285 || t == MYSQL_TYPE_MEDIUM_BLOB
269- || t == MYSQL_TYPE_LONG_BLOB;
286+ || t == MYSQL_TYPE_LONG_BLOB
287+ || t == MYSQL_TYPE_JSON;
270288}
271289
272- static bool qIsTimeOrDate (int t)
290+ static bool qIsTimeOrDate (enum_field_types t)
273291{
274292 // *not* MYSQL_TYPE_TIME because its range is bigger than QTime
275293 // (see above)
@@ -286,7 +304,7 @@ static bool qIsInteger(int t)
286304
287305void QMYSQLResultPrivate::bindBlobs ()
288306{
289- for (int i = 0 ; i < fields.count (); ++i) {
307+ for (int i = 0 ; i < fields.size (); ++i) {
290308 const MYSQL_FIELD *fieldInfo = fields.at (i).myField ;
291309 if (qIsBlob (inBinds[i].buffer_type ) && meta && fieldInfo) {
292310 MYSQL_BIND *bind = &inBinds[i];
@@ -328,7 +346,7 @@ bool QMYSQLResultPrivate::bindInValues()
328346 bind->buffer_length = f.bufLength = 0 ;
329347 hasBlobs = true ;
330348 } else if (qIsTimeOrDate (fieldInfo->type )) {
331- bind->buffer_length = f.bufLength = sizeof (MYSQL_TIME );
349+ bind->buffer_length = f.bufLength = sizeof (QT_MYSQL_TIME );
332350 } else if (qIsInteger (f.type .id ())) {
333351 bind->buffer_length = f.bufLength = 8 ;
334352 } else {
@@ -392,7 +410,7 @@ void QMYSQLResult::cleanup()
392410 }
393411
394412 int i;
395- for (i = 0 ; i < d->fields .count (); ++i)
413+ for (i = 0 ; i < d->fields .size (); ++i)
396414 delete[] d->fields [i].outField ;
397415
398416 if (d->outBinds ) {
@@ -509,7 +527,7 @@ bool QMYSQLResult::fetchFirst()
509527QVariant QMYSQLResult::data (int field)
510528{
511529 Q_D (QMYSQLResult);
512- if (!isSelect () || field >= d->fields .count ()) {
530+ if (!isSelect () || field >= d->fields .size ()) {
513531 qWarning (" QMYSQLResult::data: column %d out of range" , field);
514532 return QVariant ();
515533 }
@@ -532,8 +550,8 @@ QVariant QMYSQLResult::data(int field)
532550 else if (f.type .id () == QMetaType::Char)
533551 return variant.toInt ();
534552 return variant;
535- } else if (qIsTimeOrDate (f.myField ->type ) && f.bufLength == sizeof (MYSQL_TIME )) {
536- auto t = reinterpret_cast <const MYSQL_TIME *>(f.outField );
553+ } else if (qIsTimeOrDate (f.myField ->type ) && f.bufLength >= sizeof (QT_MYSQL_TIME )) {
554+ auto t = reinterpret_cast <const QT_MYSQL_TIME *>(f.outField );
537555 QDate date;
538556 QTime time;
539557 if (f.type .id () != QMetaType::QTime)
@@ -625,7 +643,7 @@ QVariant QMYSQLResult::data(int field)
625643bool QMYSQLResult::isNull (int field)
626644{
627645 Q_D (const QMYSQLResult);
628- if (field < 0 || field >= d->fields .count ())
646+ if (field < 0 || field >= d->fields .size ())
629647 return true ;
630648 if (d->preparedQuery )
631649 return d->fields .at (field).nullIndicator ;
@@ -644,7 +662,7 @@ bool QMYSQLResult::reset (const QString& query)
644662 cleanup ();
645663
646664 const QByteArray encQuery = query.toUtf8 ();
647- if (mysql_real_query (d->drv_d_func ()->mysql , encQuery.data (), encQuery.length ())) {
665+ if (mysql_real_query (d->drv_d_func ()->mysql , encQuery.data (), encQuery.size ())) {
648666 setLastError (qMakeError (QCoreApplication::translate (" QMYSQLResult" , " Unable to execute query" ),
649667 QSqlError::StatementError, d->drv_d_func ()));
650668 return false ;
@@ -752,7 +770,7 @@ bool QMYSQLResult::nextResult()
752770 d->result = 0 ;
753771 setSelect (false );
754772
755- for (int i = 0 ; i < d->fields .count (); ++i)
773+ for (int i = 0 ; i < d->fields .size (); ++i)
756774 delete[] d->fields [i].outField ;
757775 d->fields .clear ();
758776
@@ -793,13 +811,12 @@ void QMYSQLResult::virtual_hook(int id, void *data)
793811 QSqlResult::virtual_hook (id, data);
794812}
795813
796- static MYSQL_TIME *toMySqlDate (QDate date, QTime time, int type)
814+ static QT_MYSQL_TIME *toMySqlDate (QDate date, QTime time, int type)
797815{
798816 Q_ASSERT (type == QMetaType::QTime || type == QMetaType::QDate
799817 || type == QMetaType::QDateTime);
800818
801- MYSQL_TIME *myTime = new MYSQL_TIME;
802- memset (myTime, 0 , sizeof (MYSQL_TIME));
819+ auto myTime = new QT_MYSQL_TIME{};
803820
804821 if (type == QMetaType::QTime || type == QMetaType::QDateTime) {
805822 myTime->hour = time.hour ();
@@ -840,7 +857,7 @@ bool QMYSQLResult::prepare(const QString& query)
840857 }
841858
842859 const QByteArray encQuery = query.toUtf8 ();
843- r = mysql_stmt_prepare (d->stmt , encQuery.constData (), encQuery.length ());
860+ r = mysql_stmt_prepare (d->stmt , encQuery.constData (), encQuery.size ());
844861 if (r != 0 ) {
845862 setLastError (qMakeStmtError (QCoreApplication::translate (" QMYSQLResult" ,
846863 " Unable to prepare statement" ), QSqlError::StatementError, d->stmt ));
@@ -868,7 +885,7 @@ bool QMYSQLResult::exec()
868885 return false ;
869886
870887 int r = 0 ;
871- QList<MYSQL_TIME *> timeVector;
888+ QList<QT_MYSQL_TIME *> timeVector;
872889 QList<QByteArray> stringVector;
873890 QList<my_bool> nullVector;
874891
@@ -882,10 +899,10 @@ bool QMYSQLResult::exec()
882899 }
883900
884901 if (mysql_stmt_param_count (d->stmt ) > 0 &&
885- mysql_stmt_param_count (d->stmt ) == (uint)values.count ()) {
902+ mysql_stmt_param_count (d->stmt ) == (uint)values.size ()) {
886903
887- nullVector.resize (values.count ());
888- for (int i = 0 ; i < values.count (); ++i) {
904+ nullVector.resize (values.size ());
905+ for (int i = 0 ; i < values.size (); ++i) {
889906 const QVariant &val = boundValues ().at (i);
890907 void *data = const_cast <void *>(val.constData ());
891908
@@ -906,7 +923,7 @@ bool QMYSQLResult::exec()
906923 case QMetaType::QTime:
907924 case QMetaType::QDate:
908925 case QMetaType::QDateTime: {
909- MYSQL_TIME *myTime = toMySqlDate (val.toDate (), val.toTime (), val.userType ());
926+ QT_MYSQL_TIME *myTime = toMySqlDate (val.toDate (), val.toTime (), val.userType ());
910927 timeVector.append (myTime);
911928
912929 currBind->buffer = myTime;
@@ -926,7 +943,7 @@ bool QMYSQLResult::exec()
926943 default :
927944 break ;
928945 }
929- currBind->buffer_length = sizeof (MYSQL_TIME );
946+ currBind->buffer_length = sizeof (QT_MYSQL_TIME );
930947 currBind->length = 0 ;
931948 break ; }
932949 case QMetaType::UInt:
@@ -960,7 +977,7 @@ bool QMYSQLResult::exec()
960977 stringVector.append (ba);
961978 currBind->buffer_type = MYSQL_TYPE_STRING;
962979 currBind->buffer = const_cast <char *>(ba.constData ());
963- currBind->buffer_length = ba.length ();
980+ currBind->buffer_length = ba.size ();
964981 break ; }
965982 }
966983 }
@@ -1178,7 +1195,7 @@ bool QMYSQLDriver::open(const QString& db,
11781195 uint writeTimeout = 0 ;
11791196
11801197 // extract the real options from the string
1181- for (int i = 0 ; i < opts.count (); ++i) {
1198+ for (int i = 0 ; i < opts.size (); ++i) {
11821199 QString tmp (opts.at (i).simplified ());
11831200 qsizetype idx;
11841201 if ((idx = tmp.indexOf (u' =' )) != -1 ) {
0 commit comments