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>
This commit is contained in:
parent
18bd15a9ea
commit
30de1f74de
@ -215,6 +215,7 @@ static QMetaType qDecodeMYSQLType(enum_field_types mysqltype, uint flags)
|
|||||||
case MYSQL_TYPE_YEAR:
|
case MYSQL_TYPE_YEAR:
|
||||||
type = QMetaType::Int;
|
type = QMetaType::Int;
|
||||||
break;
|
break;
|
||||||
|
case MYSQL_TYPE_BIT:
|
||||||
case MYSQL_TYPE_LONGLONG:
|
case MYSQL_TYPE_LONGLONG:
|
||||||
type = (flags & UNSIGNED_FLAG) ? QMetaType::ULongLong : QMetaType::LongLong;
|
type = (flags & UNSIGNED_FLAG) ? QMetaType::ULongLong : QMetaType::LongLong;
|
||||||
break;
|
break;
|
||||||
@ -303,6 +304,11 @@ static bool qIsInteger(int t)
|
|||||||
|| t == QMetaType::LongLong || t == QMetaType::ULongLong;
|
|| t == QMetaType::LongLong || t == QMetaType::ULongLong;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool qIsBitfield(enum_field_types type)
|
||||||
|
{
|
||||||
|
return type == MYSQL_TYPE_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
void QMYSQLResultPrivate::bindBlobs()
|
void QMYSQLResultPrivate::bindBlobs()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < fields.size(); ++i) {
|
for (int i = 0; i < fields.size(); ++i) {
|
||||||
@ -519,6 +525,20 @@ bool QMYSQLResult::fetchFirst()
|
|||||||
return fetch(0);
|
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)
|
QVariant QMYSQLResult::data(int field)
|
||||||
{
|
{
|
||||||
Q_D(QMYSQLResult);
|
Q_D(QMYSQLResult);
|
||||||
@ -536,8 +556,9 @@ QVariant QMYSQLResult::data(int field)
|
|||||||
if (d->preparedQuery) {
|
if (d->preparedQuery) {
|
||||||
if (f.nullIndicator)
|
if (f.nullIndicator)
|
||||||
return QVariant(f.type);
|
return QVariant(f.type);
|
||||||
|
if (qIsBitfield(f.myField->type)) {
|
||||||
if (qIsInteger(f.type.id())) {
|
return QVariant::fromValue(qDecodeBitfield(f, f.outField));
|
||||||
|
} else if (qIsInteger(f.type.id())) {
|
||||||
QVariant variant(f.type, f.outField);
|
QVariant variant(f.type, f.outField);
|
||||||
// we never want to return char variants here, see QTBUG-53397
|
// we never want to return char variants here, see QTBUG-53397
|
||||||
if (f.type.id() == QMetaType::UChar)
|
if (f.type.id() == QMetaType::UChar)
|
||||||
@ -569,6 +590,9 @@ QVariant QMYSQLResult::data(int field)
|
|||||||
return QVariant(f.type);
|
return QVariant(f.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qIsBitfield(f.myField->type))
|
||||||
|
return QVariant::fromValue(qDecodeBitfield(f, d->row[field]));
|
||||||
|
|
||||||
fieldLength = mysql_fetch_lengths(d->result)[field];
|
fieldLength = mysql_fetch_lengths(d->result)[field];
|
||||||
|
|
||||||
if (f.type.id() != QMetaType::QByteArray)
|
if (f.type.id() != QMetaType::QByteArray)
|
||||||
@ -677,6 +701,7 @@ bool QMYSQLResult::reset (const QString& query)
|
|||||||
for(int i = 0; i < numFields; i++) {
|
for(int i = 0; i < numFields; i++) {
|
||||||
MYSQL_FIELD* field = mysql_fetch_field_direct(d->result, i);
|
MYSQL_FIELD* field = mysql_fetch_field_direct(d->result, i);
|
||||||
d->fields[i].type = qDecodeMYSQLType(field->type, field->flags);
|
d->fields[i].type = qDecodeMYSQLType(field->type, field->flags);
|
||||||
|
d->fields[i].myField = field;
|
||||||
}
|
}
|
||||||
setAt(QSql::BeforeFirstRow);
|
setAt(QSql::BeforeFirstRow);
|
||||||
}
|
}
|
||||||
@ -794,6 +819,7 @@ bool QMYSQLResult::nextResult()
|
|||||||
for (unsigned int i = 0; i < numFields; i++) {
|
for (unsigned int i = 0; i < numFields; i++) {
|
||||||
MYSQL_FIELD *field = mysql_fetch_field_direct(d->result, i);
|
MYSQL_FIELD *field = mysql_fetch_field_direct(d->result, i);
|
||||||
d->fields[i].type = qDecodeMYSQLType(field->type, field->flags);
|
d->fields[i].type = qDecodeMYSQLType(field->type, field->flags);
|
||||||
|
d->fields[i].myField = field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4629,6 +4629,13 @@ void tst_QSqlQuery::integralTypesMysql()
|
|||||||
runIntegralTypesMysqlTest<qint64>(db, "bigIntTest", "BIGINT", withPreparedStatement);
|
runIntegralTypesMysqlTest<qint64>(db, "bigIntTest", "BIGINT", withPreparedStatement);
|
||||||
runIntegralTypesMysqlTest<quint64>(db, "unsignedBigIntTest", "BIGINT UNSIGNED",
|
runIntegralTypesMysqlTest<quint64>(db, "unsignedBigIntTest", "BIGINT UNSIGNED",
|
||||||
withPreparedStatement);
|
withPreparedStatement);
|
||||||
|
runIntegralTypesMysqlTest<quint64>(db, "bitmask_7", "BIT(7)", withPreparedStatement, 0,
|
||||||
|
(1LL << 7) - 1);
|
||||||
|
runIntegralTypesMysqlTest<quint64>(db, "bitmask_31", "BIT(31)", withPreparedStatement, 0,
|
||||||
|
(1LL << 31) - 1);
|
||||||
|
runIntegralTypesMysqlTest<quint64>(db, "bitmask_33", "BIT(33)", withPreparedStatement, 0,
|
||||||
|
(1LL << 33) - 1);
|
||||||
|
runIntegralTypesMysqlTest<quint64>(db, "bitmask_64", "BIT(64)", withPreparedStatement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user