summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2021-08-13 15:19:55 -0700
committerThiago Macieira <thiago.macieira@intel.com>2021-09-29 10:46:19 -0700
commitb3e0cdedc681c27e9b2b2dcdd4f1e1420adf5a73 (patch)
tree6de62c3c80d1fe48d3f839655fdd81bbd7a0b5ae
parentab4e78b435bbd08b2b00f86360c729519846eeaf (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 Fixes: QTBUG-95639 Change-Id: I4a40ccbd3321467a8429fffd169afdbb26cf29f6 Reviewed-by: Andy Shaw <andy.shaw@qt.io> (cherry picked from commit 549ee216fd5bf2b3810e940bcbd4bbd8c64ac73f) Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/plugins/sqldrivers/mysql/qsql_mysql.cpp39
1 files changed, 17 insertions, 22 deletions
diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
index f2ae3fbc47..e43c196c10 100644
--- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
+++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
@@ -234,14 +234,14 @@ public:
struct QMyField
{
QMyField()
- : outField(0), nullIndicator(false), bufLength(0ul),
- myField(0), type(QVariant::Invalid)
+ : outField(0), myField(Q_NULLPTR), bufLength(0ul),
+ type(QVariant::Invalid), nullIndicator(false)
{}
char *outField;
- my_bool nullIndicator;
+ const MYSQL_FIELD *myField;
ulong bufLength;
- MYSQL_FIELD *myField;
QVariant::Type type;
+ my_bool nullIndicator;
};
QVector<QMyField> fields;
@@ -378,12 +378,10 @@ 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;
@@ -396,8 +394,6 @@ void QMYSQLResultPrivate::bindBlobs()
bool QMYSQLResultPrivate::bindInValues()
{
- MYSQL_BIND *bind;
- char *field;
int i = 0;
if (!meta)
@@ -410,35 +406,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;
}