connectivity/source/drivers/firebird/PreparedStatement.cxx | 30 ++++++------- 1 file changed, 16 insertions(+), 14 deletions(-)
New commits: commit b25164a3a4c47a9c5a9f31a8feb08a8aa0f8f401 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Mon Aug 5 22:01:37 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Tue Aug 6 06:54:24 2024 +0200 tdf#162340: handle target column scale in setObjectWithInfo In commit f1121362f3dd4287577dd7952c6f00a524a81111 (tdf#156530: fix OPreparedStatement::setString, 2024-07-03), I misused the method's 'scale' argument, as the number of decimals in the target column. It seems that the method was modelled after JDBC's setObject taking four arguments [1], which use is also unclear to me, but it likely is intended to describe input data. Anyway, all our implementations either pass the scale to next implementation, or ignore it. The problem was when 'x' was a string like '0.1370', and 'scale' was 0. The passed 'scale' was used, instead of the target column's; and that incorrectly truncated the number to 0. [1] https://docs.oracle.com/javase/8/docs/api/java/sql/PreparedStatement.html#setObject-int-java.lang.Object-int-int- Change-Id: Ib507d32706551517cc0a8a3cba351093549d7026 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171506 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/connectivity/source/drivers/firebird/PreparedStatement.cxx b/connectivity/source/drivers/firebird/PreparedStatement.cxx index f761365fb5bb..62eec1ceaa42 100644 --- a/connectivity/source/drivers/firebird/PreparedStatement.cxx +++ b/connectivity/source/drivers/firebird/PreparedStatement.cxx @@ -259,7 +259,7 @@ void SAL_CALL OPreparedStatement::setString(sal_Int32 nParameterIndex, break; case DataType::NUMERIC: case DataType::DECIMAL: - return setObjectWithInfo(nParameterIndex, Any{ sInput }, sdbcType, columnType.getScale()); + return setObjectWithInfo(nParameterIndex, Any{ sInput }, sdbcType, 0); break; case DataType::BOOLEAN: { @@ -395,8 +395,8 @@ sal_Int64 toNumericWithoutDecimalPlace(const Any& x, sal_Int32 scale) buffer.remove(dotPos, 1); if (scale < 0) { - assert(buffer.getLength() >= -scale); - buffer.truncate(buffer.getLength() + scale); + const sal_Int32 n = std::min(buffer.getLength(), -scale); + buffer.truncate(buffer.getLength() - n); scale = 0; } } @@ -535,8 +535,7 @@ void SAL_CALL OPreparedStatement::setDouble(sal_Int32 nIndex, double nValue) return setValue(nIndex, static_cast<sal_Int64>(nValue), columnType.getType()); case DataType::NUMERIC: case DataType::DECIMAL: - // take decimal places into account, later on they are removed in makeNumericString - return setObjectWithInfo(nIndex, Any{ nValue }, sdbcType, columnType.getScale()); + return setObjectWithInfo(nIndex, Any{ nValue }, sdbcType, 0); // TODO: SQL_D_FLOAT? } setValue<double>(nIndex, nValue, SQL_DOUBLE); @@ -830,23 +829,26 @@ void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, c checkParameterIndex(parameterIndex); setParameterNull(parameterIndex, false); - XSQLVAR* pVar = m_pInSqlda->sqlvar + (parameterIndex - 1); - int dType = (pVar->sqltype & ~1); // drop null flag + ColumnTypeInfo columnType{ m_pInSqlda, parameterIndex }; + int dType = columnType.getType() & ~1; // drop null flag if(sqlType == DataType::DECIMAL || sqlType == DataType::NUMERIC) { switch(dType) { case SQL_SHORT: - return setValue(parameterIndex, - static_cast<sal_Int16>(toNumericWithoutDecimalPlace(x, scale)), - dType); + return setValue( + parameterIndex, + static_cast<sal_Int16>(toNumericWithoutDecimalPlace(x, columnType.getScale())), + dType); case SQL_LONG: - return setValue(parameterIndex, - static_cast<sal_Int32>(toNumericWithoutDecimalPlace(x, scale)), - dType); + return setValue( + parameterIndex, + static_cast<sal_Int32>(toNumericWithoutDecimalPlace(x, columnType.getScale())), + dType); case SQL_INT64: - return setValue(parameterIndex, toNumericWithoutDecimalPlace(x, scale), dType); + return setValue(parameterIndex, + toNumericWithoutDecimalPlace(x, columnType.getScale()), dType); case SQL_DOUBLE: return setValue(parameterIndex, toDouble(x), dType); default: