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>
This commit is contained in:
Christian Ehrlicher 2024-04-21 14:15:33 +02:00
parent ab06d402dd
commit 3abb1e7b54

View File

@ -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;