summaryrefslogtreecommitdiffstats
path: root/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
diff options
context:
space:
mode:
authorChristian Ehrlicher <ch.ehrlicher@gmx.de>2023-03-10 22:24:18 +0100
committerChristian Ehrlicher <ch.ehrlicher@gmx.de>2023-03-12 16:21:17 +0000
commit30de1f74def7008b55a8a6d88a6b0f935bc6e2f8 (patch)
tree7c93082d0205dc60cbb2a12e497ceef045596a8c /src/plugins/sqldrivers/mysql/qsql_mysql.cpp
parent18bd15a9eac88adb1de1f877b112e255b19353b6 (diff)
SQL/MySQL: Add support for Bit-Value Type - BIT
Add support for MYSQL_TYPE_BIT. Since the bitfield can be max 64bits, store it in a uint64_t. Writing such a value as MYSQL_TYPE_LONGLONG works as expected but receiving it needs a special handling. [ChangeLog][SQL][MySQL] Added handling for Bit-Value Type - BIT. Fixes: QTBUG-21326 Change-Id: Id20e3316caf6703b3bec8a828144494a20693fd8 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/plugins/sqldrivers/mysql/qsql_mysql.cpp')
-rw-r--r--src/plugins/sqldrivers/mysql/qsql_mysql.cpp30
1 files changed, 28 insertions, 2 deletions
diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
index e1d230e511..1cf6798cd9 100644
--- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
+++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
@@ -215,6 +215,7 @@ static QMetaType qDecodeMYSQLType(enum_field_types mysqltype, uint flags)
case MYSQL_TYPE_YEAR:
type = QMetaType::Int;
break;
+ case MYSQL_TYPE_BIT:
case MYSQL_TYPE_LONGLONG:
type = (flags & UNSIGNED_FLAG) ? QMetaType::ULongLong : QMetaType::LongLong;
break;
@@ -303,6 +304,11 @@ static bool qIsInteger(int t)
|| t == QMetaType::LongLong || t == QMetaType::ULongLong;
}
+static inline bool qIsBitfield(enum_field_types type)
+{
+ return type == MYSQL_TYPE_BIT;
+}
+
void QMYSQLResultPrivate::bindBlobs()
{
for (int i = 0; i < fields.size(); ++i) {
@@ -519,6 +525,20 @@ bool QMYSQLResult::fetchFirst()
return fetch(0);
}
+static inline uint64_t
+qDecodeBitfield(const QMYSQLResultPrivate::QMyField &f, const char *outField)
+{
+ // byte-aligned length
+ const auto numBytes = (f.myField->length + 7) / 8;
+ uint64_t val = 0;
+ for (unsigned long i = 0; i < numBytes && outField; ++i) {
+ uint64_t tmp = static_cast<uint8_t>(outField[i]);
+ val <<= 8;
+ val |= tmp;
+ }
+ return val;
+}
+
QVariant QMYSQLResult::data(int field)
{
Q_D(QMYSQLResult);
@@ -536,8 +556,9 @@ QVariant QMYSQLResult::data(int field)
if (d->preparedQuery) {
if (f.nullIndicator)
return QVariant(f.type);
-
- if (qIsInteger(f.type.id())) {
+ if (qIsBitfield(f.myField->type)) {
+ return QVariant::fromValue(qDecodeBitfield(f, f.outField));
+ } else if (qIsInteger(f.type.id())) {
QVariant variant(f.type, f.outField);
// we never want to return char variants here, see QTBUG-53397
if (f.type.id() == QMetaType::UChar)
@@ -569,6 +590,9 @@ QVariant QMYSQLResult::data(int field)
return QVariant(f.type);
}
+ if (qIsBitfield(f.myField->type))
+ return QVariant::fromValue(qDecodeBitfield(f, d->row[field]));
+
fieldLength = mysql_fetch_lengths(d->result)[field];
if (f.type.id() != QMetaType::QByteArray)
@@ -677,6 +701,7 @@ bool QMYSQLResult::reset (const QString& query)
for(int i = 0; i < numFields; i++) {
MYSQL_FIELD* field = mysql_fetch_field_direct(d->result, i);
d->fields[i].type = qDecodeMYSQLType(field->type, field->flags);
+ d->fields[i].myField = field;
}
setAt(QSql::BeforeFirstRow);
}
@@ -794,6 +819,7 @@ bool QMYSQLResult::nextResult()
for (unsigned int i = 0; i < numFields; i++) {
MYSQL_FIELD *field = mysql_fetch_field_direct(d->result, i);
d->fields[i].type = qDecodeMYSQLType(field->type, field->flags);
+ d->fields[i].myField = field;
}
}