summaryrefslogtreecommitdiffstats
path: root/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/sqldrivers/mysql/qsql_mysql.cpp')
-rw-r--r--src/plugins/sqldrivers/mysql/qsql_mysql.cpp123
1 files changed, 70 insertions, 53 deletions
diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
index 450d551ac5..02e76db950 100644
--- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
+++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
@@ -29,10 +29,26 @@ Q_DECLARE_METATYPE(MYSQL_RES*)
Q_DECLARE_METATYPE(MYSQL*)
Q_DECLARE_METATYPE(MYSQL_STMT*)
+// MYSQL_TYPE_JSON was introduced with MySQL 5.7.9
+#if defined(MYSQL_VERSION_ID) && MYSQL_VERSION_ID < 50709
+#define MYSQL_TYPE_JSON 245
+#endif
+
// MySQL above version 8 removed my_bool typedef while MariaDB kept it,
// 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;
@@ -80,7 +96,7 @@ static inline QVariant qDateTimeFromString(QString &val)
#else
if (val.isEmpty())
return QVariant(QDateTime());
- if (val.length() == 14)
+ if (val.size() == 14)
// TIMESTAMPS have the format yyyyMMddhhmmss
val.insert(4, u'-').insert(7, u'-').insert(10, u'T').insert(13, u':').insert(16, u':');
return QVariant(QDateTime::fromString(val, Qt::ISODate));
@@ -181,58 +197,59 @@ static QSqlError qMakeError(const QString& err, QSqlError::ErrorType type,
}
-static QMetaType qDecodeMYSQLType(int mysqltype, uint flags)
+static QMetaType qDecodeMYSQLType(enum_field_types mysqltype, uint flags)
{
QMetaType::Type type;
switch (mysqltype) {
- case FIELD_TYPE_TINY :
+ case MYSQL_TYPE_TINY:
type = (flags & UNSIGNED_FLAG) ? QMetaType::UChar : QMetaType::Char;
break;
- case FIELD_TYPE_SHORT :
+ case MYSQL_TYPE_SHORT:
type = (flags & UNSIGNED_FLAG) ? QMetaType::UShort : QMetaType::Short;
break;
- case FIELD_TYPE_LONG :
- case FIELD_TYPE_INT24 :
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_INT24:
type = (flags & UNSIGNED_FLAG) ? QMetaType::UInt : QMetaType::Int;
break;
- case FIELD_TYPE_YEAR :
+ case MYSQL_TYPE_YEAR:
type = QMetaType::Int;
break;
- case FIELD_TYPE_LONGLONG :
+ case MYSQL_TYPE_LONGLONG:
type = (flags & UNSIGNED_FLAG) ? QMetaType::ULongLong : QMetaType::LongLong;
break;
- case FIELD_TYPE_FLOAT :
- case FIELD_TYPE_DOUBLE :
- case FIELD_TYPE_DECIMAL :
-#if defined(FIELD_TYPE_NEWDECIMAL)
- case FIELD_TYPE_NEWDECIMAL:
-#endif
+ case MYSQL_TYPE_FLOAT:
+ case MYSQL_TYPE_DOUBLE:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
type = QMetaType::Double;
break;
- case FIELD_TYPE_DATE :
+ case MYSQL_TYPE_DATE:
type = QMetaType::QDate;
break;
- case FIELD_TYPE_TIME :
+ case MYSQL_TYPE_TIME:
// A time field can be within the range '-838:59:59' to '838:59:59' so
// use QString instead of QTime since QTime is limited to 24 hour clock
type = QMetaType::QString;
break;
- case FIELD_TYPE_DATETIME :
- case FIELD_TYPE_TIMESTAMP :
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP:
type = QMetaType::QDateTime;
break;
- case FIELD_TYPE_STRING :
- case FIELD_TYPE_VAR_STRING :
- case FIELD_TYPE_BLOB :
- case FIELD_TYPE_TINY_BLOB :
- case FIELD_TYPE_MEDIUM_BLOB :
- case FIELD_TYPE_LONG_BLOB :
- case FIELD_TYPE_GEOMETRY :
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_GEOMETRY:
+ case MYSQL_TYPE_JSON:
type = (flags & BINARY_FLAG) ? QMetaType::QByteArray : QMetaType::QString;
break;
- default:
- case FIELD_TYPE_ENUM :
- case FIELD_TYPE_SET :
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ type = QMetaType::QString;
+ break;
+ default: // needed because there are more enum values which are not available in all headers
type = QMetaType::QString;
break;
}
@@ -242,7 +259,7 @@ static QMetaType qDecodeMYSQLType(int mysqltype, uint flags)
static QSqlField qToField(MYSQL_FIELD *field)
{
QSqlField f(QString::fromUtf8(field->name),
- qDecodeMYSQLType(int(field->type), field->flags),
+ qDecodeMYSQLType(field->type, field->flags),
QString::fromUtf8(field->table));
f.setRequired(IS_NOT_NULL(field->flags));
f.setLength(field->length);
@@ -261,15 +278,16 @@ static QSqlError qMakeStmtError(const QString& err, QSqlError::ErrorType type,
type, QString::number(mysql_stmt_errno(stmt)));
}
-static bool qIsBlob(int t)
+static bool qIsBlob(enum_field_types t)
{
return t == MYSQL_TYPE_TINY_BLOB
|| t == MYSQL_TYPE_BLOB
|| t == MYSQL_TYPE_MEDIUM_BLOB
- || t == MYSQL_TYPE_LONG_BLOB;
+ || t == MYSQL_TYPE_LONG_BLOB
+ || t == MYSQL_TYPE_JSON;
}
-static bool qIsTimeOrDate(int t)
+static bool qIsTimeOrDate(enum_field_types t)
{
// *not* MYSQL_TYPE_TIME because its range is bigger than QTime
// (see above)
@@ -286,7 +304,7 @@ static bool qIsInteger(int t)
void QMYSQLResultPrivate::bindBlobs()
{
- for (int i = 0; i < fields.count(); ++i) {
+ for (int i = 0; i < fields.size(); ++i) {
const MYSQL_FIELD *fieldInfo = fields.at(i).myField;
if (qIsBlob(inBinds[i].buffer_type) && meta && fieldInfo) {
MYSQL_BIND *bind = &inBinds[i];
@@ -328,7 +346,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 {
@@ -392,7 +410,7 @@ void QMYSQLResult::cleanup()
}
int i;
- for (i = 0; i < d->fields.count(); ++i)
+ for (i = 0; i < d->fields.size(); ++i)
delete[] d->fields[i].outField;
if (d->outBinds) {
@@ -509,7 +527,7 @@ bool QMYSQLResult::fetchFirst()
QVariant QMYSQLResult::data(int field)
{
Q_D(QMYSQLResult);
- if (!isSelect() || field >= d->fields.count()) {
+ if (!isSelect() || field >= d->fields.size()) {
qWarning("QMYSQLResult::data: column %d out of range", field);
return QVariant();
}
@@ -532,8 +550,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<const MYSQL_TIME *>(f.outField);
+ } else if (qIsTimeOrDate(f.myField->type) && f.bufLength >= sizeof(QT_MYSQL_TIME)) {
+ auto t = reinterpret_cast<const QT_MYSQL_TIME *>(f.outField);
QDate date;
QTime time;
if (f.type.id() != QMetaType::QTime)
@@ -625,7 +643,7 @@ QVariant QMYSQLResult::data(int field)
bool QMYSQLResult::isNull(int field)
{
Q_D(const QMYSQLResult);
- if (field < 0 || field >= d->fields.count())
+ if (field < 0 || field >= d->fields.size())
return true;
if (d->preparedQuery)
return d->fields.at(field).nullIndicator;
@@ -644,7 +662,7 @@ bool QMYSQLResult::reset (const QString& query)
cleanup();
const QByteArray encQuery = query.toUtf8();
- if (mysql_real_query(d->drv_d_func()->mysql, encQuery.data(), encQuery.length())) {
+ if (mysql_real_query(d->drv_d_func()->mysql, encQuery.data(), encQuery.size())) {
setLastError(qMakeError(QCoreApplication::translate("QMYSQLResult", "Unable to execute query"),
QSqlError::StatementError, d->drv_d_func()));
return false;
@@ -752,7 +770,7 @@ bool QMYSQLResult::nextResult()
d->result = 0;
setSelect(false);
- for (int i = 0; i < d->fields.count(); ++i)
+ for (int i = 0; i < d->fields.size(); ++i)
delete[] d->fields[i].outField;
d->fields.clear();
@@ -793,13 +811,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();
@@ -840,7 +857,7 @@ bool QMYSQLResult::prepare(const QString& query)
}
const QByteArray encQuery = query.toUtf8();
- r = mysql_stmt_prepare(d->stmt, encQuery.constData(), encQuery.length());
+ r = mysql_stmt_prepare(d->stmt, encQuery.constData(), encQuery.size());
if (r != 0) {
setLastError(qMakeStmtError(QCoreApplication::translate("QMYSQLResult",
"Unable to prepare statement"), QSqlError::StatementError, d->stmt));
@@ -868,7 +885,7 @@ bool QMYSQLResult::exec()
return false;
int r = 0;
- QList<MYSQL_TIME *> timeVector;
+ QList<QT_MYSQL_TIME *> timeVector;
QList<QByteArray> stringVector;
QList<my_bool> nullVector;
@@ -882,10 +899,10 @@ bool QMYSQLResult::exec()
}
if (mysql_stmt_param_count(d->stmt) > 0 &&
- mysql_stmt_param_count(d->stmt) == (uint)values.count()) {
+ mysql_stmt_param_count(d->stmt) == (uint)values.size()) {
- nullVector.resize(values.count());
- for (int i = 0; i < values.count(); ++i) {
+ nullVector.resize(values.size());
+ for (int i = 0; i < values.size(); ++i) {
const QVariant &val = boundValues().at(i);
void *data = const_cast<void *>(val.constData());
@@ -906,7 +923,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;
@@ -926,7 +943,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:
@@ -960,7 +977,7 @@ bool QMYSQLResult::exec()
stringVector.append(ba);
currBind->buffer_type = MYSQL_TYPE_STRING;
currBind->buffer = const_cast<char *>(ba.constData());
- currBind->buffer_length = ba.length();
+ currBind->buffer_length = ba.size();
break; }
}
}
@@ -1178,7 +1195,7 @@ bool QMYSQLDriver::open(const QString& db,
uint writeTimeout = 0;
// extract the real options from the string
- for (int i = 0; i < opts.count(); ++i) {
+ for (int i = 0; i < opts.size(); ++i) {
QString tmp(opts.at(i).simplified());
qsizetype idx;
if ((idx = tmp.indexOf(u'=')) != -1) {