From e1d874a71bd6f23c924c9c0bb7676811734bd6a1 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Fri, 6 Jun 2025 22:10:27 +0200 Subject: [PATCH] SQL/ODBC: misc cleanup Misc cleanup - merge qGetIntData and qGetBigIntData - remove unused braces - properly initialize values Change-Id: I0867dbbfa611087cd470b821f1f8d7ed74ed0aae Reviewed-by: Axel Spoerl (cherry picked from commit 4896448ffd54178c3e9fa2cba0070ce3a936ed05) Reviewed-by: Qt Cherry-pick Bot --- src/plugins/sqldrivers/odbc/qsql_odbc.cpp | 98 ++++++++++------------- 1 file changed, 42 insertions(+), 56 deletions(-) diff --git a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp index e09e65f223a..03b0b7d3000 100644 --- a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp +++ b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp @@ -343,7 +343,7 @@ static QSqlError qMakeError(const QString &err, return errorFromDiagRecords(err, type, qODBCWarn(p)); } -static QMetaType qDecodeODBCType(SQLSMALLINT sqltype, bool isSigned = true) +static QMetaType qDecodeODBCType(SQLSMALLINT sqltype, bool isSigned) { int type = QMetaType::UnknownType; switch (sqltype) { @@ -526,29 +526,33 @@ static QVariant qGetBinaryData(SQLHANDLE hStmt, int column) return fieldVal; } -static QVariant qGetIntData(SQLHANDLE hStmt, int column, bool isSigned = true) +template +static QVariant qGetIntData(SQLHANDLE hStmt, int column) { - SQLINTEGER intbuf = 0; + constexpr auto isSigned = std::is_signed(); + constexpr auto is16BitType = sizeof(T) == 2; + constexpr auto is32BitType = sizeof(T) == 4; + constexpr auto is64BitType = sizeof(T) == 8; + constexpr auto tgtType = + is16BitType ? (isSigned ? SQL_C_SSHORT : SQL_C_USHORT) + : is32BitType ? (isSigned ? SQL_C_SLONG : SQL_C_ULONG) + : (isSigned ? SQL_C_SBIGINT : SQL_C_UBIGINT); + static_assert(is16BitType || is32BitType || is64BitType, + "Can only handle 16, 32 or 64 bit integer"); + T intbuf = 0; SQLLEN lengthIndicator = 0; - SQLRETURN r = SQLGetData(hStmt, - column+1, - isSigned ? SQL_C_SLONG : SQL_C_ULONG, - (SQLPOINTER)&intbuf, - sizeof(intbuf), - &lengthIndicator); + SQLRETURN r = SQLGetData(hStmt, column + 1, tgtType, + (SQLPOINTER)&intbuf, sizeof(intbuf), &lengthIndicator); if (!SQL_SUCCEEDED(r)) return QVariant(); if (lengthIndicator == SQL_NULL_DATA) - return QVariant(QMetaType::fromType()); - if (isSigned) - return int(intbuf); - else - return uint(intbuf); + return QVariant(QMetaType::fromType()); + return QVariant::fromValue(intbuf); } static QVariant qGetDoubleData(SQLHANDLE hStmt, int column) { - SQLDOUBLE dblbuf; + SQLDOUBLE dblbuf = 0; SQLLEN lengthIndicator = 0; SQLRETURN r = SQLGetData(hStmt, column+1, @@ -556,37 +560,14 @@ static QVariant qGetDoubleData(SQLHANDLE hStmt, int column) (SQLPOINTER) &dblbuf, 0, &lengthIndicator); - if (!SQL_SUCCEEDED(r)) { + if (!SQL_SUCCEEDED(r)) return QVariant(); - } if (lengthIndicator == SQL_NULL_DATA) return QVariant(QMetaType::fromType()); return (double) dblbuf; } - -static QVariant qGetBigIntData(SQLHANDLE hStmt, int column, bool isSigned = true) -{ - SQLBIGINT lngbuf = 0; - SQLLEN lengthIndicator = 0; - SQLRETURN r = SQLGetData(hStmt, - column+1, - isSigned ? SQL_C_SBIGINT : SQL_C_UBIGINT, - (SQLPOINTER) &lngbuf, - sizeof(lngbuf), - &lengthIndicator); - if (!SQL_SUCCEEDED(r)) - return QVariant(); - if (lengthIndicator == SQL_NULL_DATA) - return QVariant(QMetaType::fromType()); - - if (isSigned) - return qint64(lngbuf); - else - return quint64(lngbuf); -} - static bool isAutoValue(const SQLHANDLE hStmt, int column) { SQLLEN nNumericAttribute = 0; // Check for auto-increment @@ -605,13 +586,13 @@ static bool isAutoValue(const SQLHANDLE hStmt, int column) static QSqlField qMakeFieldInfo(const SQLHANDLE hStmt, const QODBCDriverPrivate* p) { QString fname = qGetStringData(hStmt, 3, -1, p->unicode).toString(); - int type = qGetIntData(hStmt, 4).toInt(); // column type - QSqlField f(fname, qDecodeODBCType(type, p)); - QVariant var = qGetIntData(hStmt, 6); + int type = qGetIntData(hStmt, 4).toInt(); // column type + QSqlField f(fname, qDecodeODBCType(type, true)); // signed, we don't know better here + QVariant var = qGetIntData(hStmt, 6); f.setLength(var.isNull() ? -1 : var.toInt()); // column size - var = qGetIntData(hStmt, 8).toInt(); + var = qGetIntData(hStmt, 8).toInt(); f.setPrecision(var.isNull() ? -1 : var.toInt()); // precision - int required = qGetIntData(hStmt, 10).toInt(); // nullable-flag + int required = qGetIntData(hStmt, 10).toInt(); // nullable-flag // required can be SQL_NO_NULLS, SQL_NULLABLE or SQL_NULLABLE_UNKNOWN if (required == SQL_NO_NULLS) f.setRequired(true); @@ -1002,9 +983,8 @@ bool QODBCResult::reset (const QString& query) SQLNumResultCols(d->hStmt, &count); if (count) { setSelect(true); - for (SQLSMALLINT i = 0; i < count; ++i) { + for (SQLSMALLINT i = 0; i < count; ++i) d->rInf.append(qMakeFieldInfo(d, i)); - } d->fieldCache.resize(count); } else { setSelect(false); @@ -1177,18 +1157,22 @@ QVariant QODBCResult::data(int field) const QSqlField info = d->rInf.field(i); switch (info.metaType().id()) { case QMetaType::LongLong: - d->fieldCache[i] = qGetBigIntData(d->hStmt, i); - break; - case QMetaType::ULongLong: - d->fieldCache[i] = qGetBigIntData(d->hStmt, i, false); + d->fieldCache[i] = qGetIntData(d->hStmt, i); break; case QMetaType::Int: + d->fieldCache[i] = qGetIntData(d->hStmt, i); + break; case QMetaType::Short: - d->fieldCache[i] = qGetIntData(d->hStmt, i); + d->fieldCache[i] = qGetIntData(d->hStmt, i); + break; + case QMetaType::ULongLong: + d->fieldCache[i] = qGetIntData(d->hStmt, i); break; case QMetaType::UInt: + d->fieldCache[i] = qGetIntData(d->hStmt, i); + break; case QMetaType::UShort: - d->fieldCache[i] = qGetIntData(d->hStmt, i, false); + d->fieldCache[i] = qGetIntData(d->hStmt, i); break; case QMetaType::QDate: DATE_STRUCT dbuf; @@ -1239,10 +1223,10 @@ QVariant QODBCResult::data(int field) case QMetaType::Double: switch(numericalPrecisionPolicy()) { case QSql::LowPrecisionInt32: - d->fieldCache[i] = qGetIntData(d->hStmt, i); + d->fieldCache[i] = qGetIntData(d->hStmt, i); break; case QSql::LowPrecisionInt64: - d->fieldCache[i] = qGetBigIntData(d->hStmt, i); + d->fieldCache[i] = qGetIntData(d->hStmt, i); break; case QSql::LowPrecisionDouble: d->fieldCache[i] = qGetDoubleData(d->hStmt, i); @@ -1300,6 +1284,9 @@ bool QODBCResult::prepare(const QString& query) SQLRETURN r; d->rInf.clear(); + d->fieldCache.clear(); + d->fieldCacheIdx = 0; + if (d->hStmt && d->isStmtHandleValid()) { r = SQLFreeHandle(SQL_HANDLE_STMT, d->hStmt); if (r != SQL_SUCCESS) { @@ -1676,9 +1663,8 @@ bool QODBCResult::exec() SQLNumResultCols(d->hStmt, &count); if (count) { setSelect(true); - for (SQLSMALLINT i = 0; i < count; ++i) { + for (SQLSMALLINT i = 0; i < count; ++i) d->rInf.append(qMakeFieldInfo(d, i)); - } d->fieldCache.resize(count); } else { setSelect(false);