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