diff options
Diffstat (limited to 'src/plugins/sqldrivers/mysql/qsql_mysql.cpp')
-rw-r--r-- | src/plugins/sqldrivers/mysql/qsql_mysql.cpp | 57 |
1 files changed, 34 insertions, 23 deletions
diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp index a641935dc5..6c522838df 100644 --- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp +++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp @@ -158,6 +158,20 @@ static inline QVariant qDateTimeFromString(QString &val) #endif } +// check if this client and server version of MySQL/MariaDB support prepared statements +static inline bool checkPreparedQueries(MYSQL *mysql) +{ + std::unique_ptr<MYSQL_STMT, decltype(&mysql_stmt_close)> stmt(mysql_stmt_init(mysql), &mysql_stmt_close); + if (!stmt) + return false; + + static const char dummyQuery[] = "SELECT ? + ?"; + if (mysql_stmt_prepare(stmt.get(), dummyQuery, sizeof(dummyQuery) - 1)) + return false; + + return mysql_stmt_param_count(stmt.get()) == 2; +} + class QMYSQLResultPrivate; class QMYSQLResult : public QSqlResult @@ -209,7 +223,7 @@ public: struct QMyField { char *outField = nullptr; - MYSQL_FIELD *myField = nullptr; + const MYSQL_FIELD *myField = nullptr; QMetaType::Type type = QMetaType::UnknownType; my_bool nullIndicator = false; ulong bufLength = 0ul; @@ -295,6 +309,7 @@ static QMetaType::Type qDecodeMYSQLType(int mysqltype, uint flags) case FIELD_TYPE_MEDIUM_BLOB : case FIELD_TYPE_LONG_BLOB : case FIELD_TYPE_GEOMETRY : + case MYSQL_TYPE_JSON : type = (flags & BINARY_FLAG) ? QMetaType::QByteArray : QMetaType::QString; break; default: @@ -333,7 +348,8 @@ static bool qIsBlob(int 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 qIsInteger(int t) @@ -346,12 +362,9 @@ static bool qIsInteger(int t) void QMYSQLResultPrivate::bindBlobs() { - int i; - MYSQL_FIELD *fieldInfo; MYSQL_BIND *bind; - - for(i = 0; i < fields.count(); ++i) { - fieldInfo = fields.at(i).myField; + for (int i = 0; i < fields.count(); ++i) { + const MYSQL_FIELD *fieldInfo = fields.at(i).myField; if (qIsBlob(inBinds[i].buffer_type) && meta && fieldInfo) { bind = &inBinds[i]; bind->buffer_length = fieldInfo->max_length; @@ -364,8 +377,6 @@ void QMYSQLResultPrivate::bindBlobs() bool QMYSQLResultPrivate::bindInValues() { - MYSQL_BIND *bind; - char *field; int i = 0; if (!meta) @@ -378,35 +389,34 @@ bool QMYSQLResultPrivate::bindInValues() inBinds = new MYSQL_BIND[fields.size()]; memset(inBinds, 0, fields.size() * sizeof(MYSQL_BIND)); - MYSQL_FIELD *fieldInfo; + const MYSQL_FIELD *fieldInfo; while((fieldInfo = mysql_fetch_field(meta))) { + MYSQL_BIND *bind = &inBinds[i]; + QMyField &f = fields[i]; f.myField = fieldInfo; - + bind->buffer_length = f.bufLength = fieldInfo->length + 1; + bind->buffer_type = fieldInfo->type; f.type = qDecodeMYSQLType(fieldInfo->type, fieldInfo->flags); if (qIsBlob(fieldInfo->type)) { // the size of a blob-field is available as soon as we call // mysql_stmt_store_result() // after mysql_stmt_exec() in QMYSQLResult::exec() - fieldInfo->length = 0; + bind->buffer_length = f.bufLength = 0; hasBlobs = true; } else if (qIsInteger(f.type)) { - fieldInfo->length = 8; + bind->buffer_length = f.bufLength = 8; } else { - fieldInfo->type = MYSQL_TYPE_STRING; + bind->buffer_type = MYSQL_TYPE_STRING; } - bind = &inBinds[i]; - field = new char[fieldInfo->length + 1]; - memset(field, 0, fieldInfo->length + 1); - bind->buffer_type = fieldInfo->type; - bind->buffer = field; - bind->buffer_length = f.bufLength = fieldInfo->length + 1; bind->is_null = &f.nullIndicator; bind->length = &f.bufLength; bind->is_unsigned = fieldInfo->flags & UNSIGNED_FLAG ? 1 : 0; - f.outField=field; + + char *field = new char[bind->buffer_length + 1]{}; + bind->buffer = f.outField = field; ++i; } @@ -1371,8 +1381,7 @@ bool QMYSQLDriver::open(const QString& db, } #endif // MYSQL_VERSION_ID >= 50007 - d->preparedQuerysEnabled = mysql_get_client_version() >= 40108 - && mysql_get_server_version(d->mysql) >= 40100; + d->preparedQuerysEnabled = checkPreparedQueries(d->mysql); #if QT_CONFIG(thread) mysql_thread_init(); @@ -1584,3 +1593,5 @@ bool QMYSQLDriver::isIdentifierEscaped(const QString &identifier, IdentifierType } QT_END_NAMESPACE + +#include "moc_qsql_mysql_p.cpp" |