summaryrefslogtreecommitdiff
path: root/connectivity/source/drivers/firebird
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2024-07-20 04:25:34 +0500
committerMike Kaganski <mike.kaganski@collabora.com>2024-07-20 07:55:03 +0200
commit1b796287df8b3dc40ddd905c6f4822c53b36f9b1 (patch)
tree423a60a976989e8c67887956d6b14cac79adb44d /connectivity/source/drivers/firebird
parent553c128e3fdc4b9612c1150b30d7b89df2ae6fdd (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.cxx66
-rw-r--r--connectivity/source/drivers/firebird/ResultSetMetaData.cxx9
-rw-r--r--connectivity/source/drivers/firebird/Util.hxx9
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; }