diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2021-08-13 15:19:55 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2021-08-17 17:20:03 -0700 |
commit | 549ee216fd5bf2b3810e940bcbd4bbd8c64ac73f (patch) | |
tree | 57e11da84528805d070d85e37db509b5046a1a3d /src/plugins/sqldrivers/mysql/qsql_mysql.cpp | |
parent | 65aca9a223ec8853cc17bf348d4131a9f3ad233f (diff) |
MySQL: treat the MYSQL_FIELD as read-only
The MariaDB-connector-c version 3.2 and MariaDB server version 10.6
cooperate to avoid re-transferring the query metadata, so the fact that
we were modifying it was causing it to improperly decode the DATETIME
data types into string, as we had asked. We ended up with a 7-byte
string that was actually the date binary-encoded.
References:
- https://jira.mariadb.org/browse/MDEV-26271
- https://github.com/MythTV/mythtv/issues/373
- https://bugs.kde.org/show_bug.cgi?id=440296
Pick-to: 5.12 5.15 6.2
Fixes: QTBUG-95639
Change-Id: I4a40ccbd3321467a8429fffd169afdbb26cf29f6
Reviewed-by: Andy Shaw <andy.shaw@qt.io>
Diffstat (limited to 'src/plugins/sqldrivers/mysql/qsql_mysql.cpp')
-rw-r--r-- | src/plugins/sqldrivers/mysql/qsql_mysql.cpp | 27 |
1 files changed, 13 insertions, 14 deletions
diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp index 2c0ccc8399..95d5bb3b12 100644 --- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp +++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp @@ -186,7 +186,7 @@ public: struct QMyField { char *outField = nullptr; - MYSQL_FIELD *myField = nullptr; + const MYSQL_FIELD *myField = nullptr; QMetaType type = QMetaType(); my_bool nullIndicator = false; ulong bufLength = 0ul; @@ -314,7 +314,7 @@ static bool qIsInteger(int t) void QMYSQLResultPrivate::bindBlobs() { for (int i = 0; i < fields.count(); ++i) { - MYSQL_FIELD *fieldInfo = fields.at(i).myField; + const MYSQL_FIELD *fieldInfo = fields.at(i).myField; if (qIsBlob(inBinds[i].buffer_type) && meta && fieldInfo) { MYSQL_BIND *bind = &inBinds[i]; bind->buffer_length = fieldInfo->max_length; @@ -337,36 +337,35 @@ bool QMYSQLResultPrivate::bindInValues() inBinds = new MYSQL_BIND[fields.size()]; memset(inBinds, 0, fields.size() * sizeof(MYSQL_BIND)); - MYSQL_FIELD *fieldInfo; + const MYSQL_FIELD *fieldInfo; int i = 0; 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.id())) { - fieldInfo->length = 8; + bind->buffer_length = f.bufLength = 8; } else { - fieldInfo->type = MYSQL_TYPE_STRING; + bind->buffer_type = MYSQL_TYPE_STRING; } - MYSQL_BIND *bind = &inBinds[i]; - char *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; } |