connectivity/source/drivers/firebird/PreparedStatement.cxx |   66 +++++++------
 connectivity/source/drivers/firebird/ResultSetMetaData.cxx |    9 -
 connectivity/source/drivers/firebird/Util.hxx              |    9 -
 3 files changed, 44 insertions(+), 40 deletions(-)

New commits:
commit 91d9b66ed66f07abba754800482cc40964d85cc4
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Sat Jul 20 04:25:34 2024 +0500
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Tue Jul 23 08:58:31 2024 +0200

    tdf#162111: promote integer types automatically
    
    The problem was, that importing an HTML table into Firebird, and creating
    a primary key, called OParameterUpdateHelper::updateInt for each record's
    primary key field.  Since commit c07548447a564b2d142cc439a124b76e6a71dfbd
    (Related: tdf#108057 Use autoincrement for automatically added primary key,
    2024-03-20), the type of autocreated primary key in Firebird databases is
    SQL_INT64, and before this change, OPreparedStatement::setInt failed when
    the real field's type wasn't strictly SQL_LONG.
    
    This allows Firebird SDBC's  integral OPreparedStatement::set* methods to
    promote to larger numeric types capable to represent the values.
    
    Change-Id: I7615c8e9ffa29271d04cf264bb950cb76946dfd6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170787
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Tested-by: Jenkins
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170855

diff --git a/connectivity/source/drivers/firebird/PreparedStatement.cxx 
b/connectivity/source/drivers/firebird/PreparedStatement.cxx
index 4bc16e5ea13a..ce951d639bae 100644
--- a/connectivity/source/drivers/firebird/PreparedStatement.cxx
+++ b/connectivity/source/drivers/firebird/PreparedStatement.cxx
@@ -391,7 +391,6 @@ sal_Int64 toNumericWithoutDecimalPlace(const OUString& 
sSource)
 void SAL_CALL OPreparedStatement::setNull(sal_Int32 nIndex, sal_Int32 
/*nSqlType*/)
 {
     MutexGuard aGuard( m_aMutex );
-    checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
     ensurePrepared();
 
     checkParameterIndex(nIndex);
@@ -407,7 +406,6 @@ template <typename T>
 void OPreparedStatement::setValue(sal_Int32 nIndex, const T& nValue, ISC_SHORT 
nType)
 {
     MutexGuard aGuard( m_aMutex );
-    checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
     ensurePrepared();
 
     checkParameterIndex(nIndex);
@@ -426,20 +424,48 @@ void OPreparedStatement::setValue(sal_Int32 nIndex, const 
T& nValue, ISC_SHORT n
     memcpy(pVar->sqldata, &nValue, sizeof(nValue));
 }
 
+// Integral type setters convert transparently to bigger types
+
 void SAL_CALL OPreparedStatement::setByte(sal_Int32 nIndex, sal_Int8 nValue)
 {
     // there's no TINYINT or equivalent on Firebird,
     // so do the same as setShort
-    setValue< sal_Int16 >(nIndex, nValue, SQL_SHORT);
+    setShort(nIndex, nValue);
 }
 
 void SAL_CALL OPreparedStatement::setShort(sal_Int32 nIndex, sal_Int16 nValue)
 {
+    MutexGuard aGuard(m_aMutex);
+    ensurePrepared();
+
+    ColumnTypeInfo columnType{ m_pInSqlda, nIndex };
+    switch (columnType.getSdbcType())
+    {
+        case DataType::INTEGER:
+            return setValue<sal_Int32>(nIndex, nValue, columnType.getType());
+        case DataType::BIGINT:
+            return setValue<sal_Int64>(nIndex, nValue, columnType.getType());
+        case DataType::FLOAT:
+            return setValue<float>(nIndex, nValue, columnType.getType());
+        case DataType::DOUBLE:
+            return setValue<double>(nIndex, nValue, columnType.getType());
+    }
     setValue< sal_Int16 >(nIndex, nValue, SQL_SHORT);
 }
 
 void SAL_CALL OPreparedStatement::setInt(sal_Int32 nIndex, sal_Int32 nValue)
 {
+    MutexGuard aGuard(m_aMutex);
+    ensurePrepared();
+
+    ColumnTypeInfo columnType{ m_pInSqlda, nIndex };
+    switch (columnType.getSdbcType())
+    {
+        case DataType::BIGINT:
+            return setValue<sal_Int64>(nIndex, nValue, columnType.getType());
+        case DataType::DOUBLE:
+            return setValue<double>(nIndex, nValue, columnType.getType());
+    }
     setValue< sal_Int32 >(nIndex, nValue, SQL_LONG);
 }
 
@@ -456,51 +482,35 @@ void SAL_CALL OPreparedStatement::setFloat(sal_Int32 
nIndex, float nValue)
 void SAL_CALL OPreparedStatement::setDouble(sal_Int32 nIndex, double nValue)
 {
     MutexGuard aGuard( m_aMutex );
-    checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed);
     ensurePrepared();
 
-    XSQLVAR* pVar = m_pInSqlda->sqlvar + (nIndex - 1);
-    short dType = (pVar->sqltype & ~1); // drop flag bit for now
-    short dSubType = pVar->sqlsubtype;
+    ColumnTypeInfo columnType{ m_pInSqlda, nIndex };
     // Assume it is a sub type of a number.
-    if(dSubType < 0 || dSubType > 2)
+    if (columnType.getSubType() < 0 || columnType.getSubType() > 2)
     {
         ::dbtools::throwSQLException(
             u"Incorrect number sub type"_ustr,
             ::dbtools::StandardSQLState::INVALID_SQL_DATA_TYPE,
             *this);
     }
-    // firebird stores scale as a negative number
-    ColumnTypeInfo columnType{ dType, dSubType,
-        static_cast<short>(-pVar->sqlscale) };
 
     // Caller might try to set an integer type here. It makes sense to convert
     // it instead of throwing an error.
-    switch(columnType.getSdbcType())
+    switch(auto sdbcType = columnType.getSdbcType())
     {
         case DataType::SMALLINT:
-            setValue< sal_Int16 >(nIndex,
-                    static_cast<sal_Int16>(nValue),
-                    dType);
-            break;
+            return setValue(nIndex, static_cast<sal_Int16>(nValue), 
columnType.getType());
         case DataType::INTEGER:
-            setValue< sal_Int32 >(nIndex,
-                    static_cast<sal_Int32>(nValue),
-                    dType);
-            break;
+            return setValue(nIndex, static_cast<sal_Int32>(nValue), 
columnType.getType());
         case DataType::BIGINT:
-            setValue< sal_Int64 >(nIndex,
-                    static_cast<sal_Int64>(nValue),
-                    dType);
-            break;
+            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
-            setObjectWithInfo(nIndex,Any{nValue}, columnType.getSdbcType(), 
columnType.getScale());
-            break;
-        default:
-            setValue< double >(nIndex, nValue, SQL_DOUBLE); // TODO: 
SQL_D_FLOAT?
+            return setObjectWithInfo(nIndex, Any{ nValue }, sdbcType, 
columnType.getScale());
+        // TODO: SQL_D_FLOAT?
     }
+    setValue<double>(nIndex, nValue, SQL_DOUBLE);
 }
 
 void SAL_CALL OPreparedStatement::setDate(sal_Int32 nIndex, const Date& rDate)
diff --git a/connectivity/source/drivers/firebird/ResultSetMetaData.cxx 
b/connectivity/source/drivers/firebird/ResultSetMetaData.cxx
index 4efabc4ab3cc..0a80c851a980 100644
--- a/connectivity/source/drivers/firebird/ResultSetMetaData.cxx
+++ b/connectivity/source/drivers/firebird/ResultSetMetaData.cxx
@@ -102,10 +102,7 @@ sal_Int32 SAL_CALL 
OResultSetMetaData::getColumnType(sal_Int32 column)
         sCharset = getCharacterSet(column);
     }
 
-    ColumnTypeInfo aInfo( m_pSqlda->sqlvar[column-1].sqltype,
-            m_pSqlda->sqlvar[column-1].sqlsubtype,
-            -(m_pSqlda->sqlvar[column-1].sqlscale),
-            sCharset );
+    ColumnTypeInfo aInfo(m_pSqlda, column, sCharset);
 
     return aInfo.getSdbcType();
 }
@@ -158,9 +155,7 @@ OUString SAL_CALL 
OResultSetMetaData::getColumnTypeName(sal_Int32 column)
 {
     verifyValidColumn(column);
 
-    ColumnTypeInfo aInfo( m_pSqlda->sqlvar[column-1].sqltype,
-            m_pSqlda->sqlvar[column-1].sqlsubtype,
-            -(m_pSqlda->sqlvar[column-1].sqlscale) );
+    ColumnTypeInfo aInfo(m_pSqlda, column);
 
     return aInfo.getColumnTypeName();
 }
diff --git a/connectivity/source/drivers/firebird/Util.hxx 
b/connectivity/source/drivers/firebird/Util.hxx
index db407ef98b38..4cbf49879465 100644
--- a/connectivity/source/drivers/firebird/Util.hxx
+++ b/connectivity/source/drivers/firebird/Util.hxx
@@ -63,11 +63,10 @@ public:
                 , m_aSubType(aSubType)
                 , m_nScale(nScale)
                 , m_sCharsetName(std::move(sCharset)) {}
-            explicit ColumnTypeInfo( short aType, OUString sCharset )
-                : m_aType(aType)
-                , m_aSubType(0)
-                , m_nScale(0)
-                , m_sCharsetName(std::move(sCharset)) {}
+            explicit ColumnTypeInfo(const XSQLVAR& var, OUString sCharset)
+                : ColumnTypeInfo(var.sqltype, var.sqlsubtype, -var.sqlscale, 
std::move(sCharset)) {}
+            explicit ColumnTypeInfo(const XSQLDA* pXSQLDA, sal_Int32 column, 
OUString sCharset = {})
+                : ColumnTypeInfo(pXSQLDA->sqlvar[column-1], 
std::move(sCharset)) {}
             short getType() const { return m_aType; }
             short getSubType() const { return m_aSubType; }
             short getScale() const { return m_nScale; }

Reply via email to