diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2024-07-20 04:25:34 +0500 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2024-07-20 07:55:03 +0200 |
commit | 1b796287df8b3dc40ddd905c6f4822c53b36f9b1 (patch) | |
tree | 423a60a976989e8c67887956d6b14cac79adb44d /connectivity/source/drivers/firebird | |
parent | 553c128e3fdc4b9612c1150b30d7b89df2ae6fdd (diff) |
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.kaganski@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'connectivity/source/drivers/firebird')
-rw-r--r-- | connectivity/source/drivers/firebird/PreparedStatement.cxx | 66 | ||||
-rw-r--r-- | connectivity/source/drivers/firebird/ResultSetMetaData.cxx | 9 | ||||
-rw-r--r-- | connectivity/source/drivers/firebird/Util.hxx | 9 |
3 files changed, 44 insertions, 40 deletions
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; } |