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:

Reply via email to