diff options
author | Christian Ehrlicher <ch.ehrlicher@gmx.de> | 2024-04-21 14:15:33 +0200 |
---|---|---|
committer | Christian Ehrlicher <ch.ehrlicher@gmx.de> | 2024-04-27 16:35:11 +0200 |
commit | 3abb1e7b542878403f28d79a24d231a9c5bf19bc (patch) | |
tree | eed7fa67b6db657222355ad86ab87adb9b755de0 | |
parent | ab06d402dd833cefe9c0d929c13e93068aab96d9 (diff) |
SQL/IBase: factor out applying decimal scale into own function
Move the calculation of the decimal scale into own function and preserve
HighPrecision string values by not converting them into doubles before.
Change-Id: I839923189e9f6b1f8fb9ce234c987423703b79bf
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
-rw-r--r-- | src/plugins/sqldrivers/ibase/qsql_ibase.cpp | 88 |
1 files changed, 51 insertions, 37 deletions
diff --git a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp index f7abb8718d..7b5f7e8eb7 100644 --- a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp +++ b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp @@ -406,6 +406,42 @@ protected: int size() override; int numRowsAffected() override; QSqlRecord record() const override; + + template<typename T> + QVariant applyScale(T val, int scale) const + { + if (scale >= 0) + return QVariant(val); + + switch (numericalPrecisionPolicy()) { + case QSql::LowPrecisionInt32: + return QVariant(qint32(val * pow(10.0, scale))); + case QSql::LowPrecisionInt64: + return QVariant(qint64(val * pow(10.0, scale))); + case QSql::LowPrecisionDouble: + return QVariant(double(val * pow(10.0, scale))); + case QSql::HighPrecision: { + const bool negative = val < 0; + QString number; + if constexpr (std::is_signed_v<T> || negative) + number = QString::number(qAbs(val)); + else + number = QString::number(val); + auto len = number.size(); + scale *= -1; + if (scale >= len) { + number = QString(scale - len + 1, u'0') + number; + len = number.size(); + } + const auto sepPos = len - scale; + number = number.left(sepPos) + u'.' + number.mid(sepPos); + if (negative) + number = u'-' + number; + return QVariant(number); + } + } + return QVariant(val); + } }; class QIBaseResultPrivate: public QSqlCachedResultPrivate @@ -1239,27 +1275,26 @@ bool QIBaseResult::gotoNext(QSqlCachedResult::ValueCache& row, int rowIdx) // pascal strings - a short with a length information followed by the data row[idx] = QString::fromUtf8(buf + sizeof(short), *(short*)buf); break; - case SQL_INT64: - if (d->sqlda->sqlvar[i].sqlscale < 0) - row[idx] = *(qint64*)buf * pow(10.0, d->sqlda->sqlvar[i].sqlscale); - else - row[idx] = QVariant(*(qint64*)buf); + case SQL_INT64: { + Q_ASSERT(d->sqlda->sqlvar[i].sqllen == sizeof(qint64)); + const auto val = *(qint64 *)buf; + const auto scale = d->sqlda->sqlvar[i].sqlscale; + row[idx] = applyScale(val, scale); break; case SQL_LONG: - if (d->sqlda->sqlvar[i].sqllen == 4) - if (d->sqlda->sqlvar[i].sqlscale < 0) - row[idx] = QVariant(*(qint32*)buf * pow(10.0, d->sqlda->sqlvar[i].sqlscale)); - else - row[idx] = QVariant(*(qint32*)buf); - else + if (d->sqlda->sqlvar[i].sqllen == 4) { + const auto val = *(qint32 *)buf; + const auto scale = d->sqlda->sqlvar[i].sqlscale; + row[idx] = applyScale(val, scale); + } else row[idx] = QVariant(*(qint64*)buf); break; - case SQL_SHORT: - if (d->sqlda->sqlvar[i].sqlscale < 0) - row[idx] = QVariant(long((*(short*)buf)) * pow(10.0, d->sqlda->sqlvar[i].sqlscale)); - else - row[idx] = QVariant(int((*(short*)buf))); + case SQL_SHORT: { + const auto val = *(short *)buf; + const auto scale = d->sqlda->sqlvar[i].sqlscale; + row[idx] = applyScale(val, scale); break; + } case SQL_FLOAT: row[idx] = QVariant(double((*(float*)buf))); break; @@ -1299,27 +1334,6 @@ bool QIBaseResult::gotoNext(QSqlCachedResult::ValueCache& row, int rowIdx) row[idx] = QVariant(); break; } - if (d->sqlda->sqlvar[i].sqlscale < 0) { - QVariant v = row[idx]; - switch(numericalPrecisionPolicy()) { - case QSql::LowPrecisionInt32: - if (v.convert(QMetaType(QMetaType::Int))) - row[idx]=v; - break; - case QSql::LowPrecisionInt64: - if (v.convert(QMetaType(QMetaType::LongLong))) - row[idx]=v; - break; - case QSql::LowPrecisionDouble: - if (v.convert(QMetaType(QMetaType::Double))) - row[idx]=v; - break; - case QSql::HighPrecision: - if (v.convert(QMetaType(QMetaType::QString))) - row[idx]=v; - break; - } - } } return true; |