summaryrefslogtreecommitdiffstats
path: root/connectivity/source/drivers/firebird/PreparedStatement.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'connectivity/source/drivers/firebird/PreparedStatement.cxx')
-rw-r--r--connectivity/source/drivers/firebird/PreparedStatement.cxx59
1 files changed, 47 insertions, 12 deletions
diff --git a/connectivity/source/drivers/firebird/PreparedStatement.cxx b/connectivity/source/drivers/firebird/PreparedStatement.cxx
index c665581f8c32..35847d021ea0 100644
--- a/connectivity/source/drivers/firebird/PreparedStatement.cxx
+++ b/connectivity/source/drivers/firebird/PreparedStatement.cxx
@@ -50,6 +50,8 @@ using namespace com::sun::star::util;
IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.firebird.PreparedStatement","com.sun.star.sdbc.PreparedStatement");
+constexpr size_t MAX_SIZE_SEGMENT = 65535; // max value of a segment of CLOB, if we want more than 65535 bytes, we need more segments
+
OPreparedStatement::OPreparedStatement( Connection* _pConnection,
const OUString& sql)
@@ -207,7 +209,8 @@ void SAL_CALL OPreparedStatement::setString(sal_Int32 nParameterIndex,
{
str = str.copy(0, max_varchar_len);
}
- const auto nLength = str.getLength();
+ const sal_uInt16 nLength = str.getLength();
+ static_assert(sizeof(nLength) == 2, "must match dest memcpy len");
memcpy(pVar->sqldata, &nLength, 2);
// Actual data
memcpy(pVar->sqldata + 2, str.getStr(), str.getLength());
@@ -331,9 +334,6 @@ sal_Bool SAL_CALL OPreparedStatement::execute()
m_aStatementHandle,
m_pOutSqlda);
- if (getStatementChangeCount() > 0)
- m_pConnection->notifyDatabaseModified();
-
return m_xResultSet.is();
// TODO: implement handling of multiple ResultSets.
}
@@ -379,7 +379,7 @@ sal_Int64 toNumericWithoutDecimalPlace(const OUString& sSource)
sBuffer.append(sNumber.subView(0, nDotIndex));
}
sBuffer.append(sNumber.subView(nDotIndex + 1));
- return sBuffer.makeStringAndClear().toInt64();
+ return o3tl::toInt64(sBuffer);
}
}
@@ -567,7 +567,7 @@ void OPreparedStatement::openBlobForWriting(isc_blob_handle& rBlobHandle, ISC_QU
if (aErr)
{
evaluateStatusVector(m_statusVector,
- OUStringConcatenation("setBlob failed on " + m_sSqlStatement),
+ Concat2View("setBlob failed on " + m_sSqlStatement),
*this);
assert(false);
}
@@ -609,9 +609,9 @@ void SAL_CALL OPreparedStatement::setClob(sal_Int32 nParameterIndex, const Refer
sal_Int64 nCharWritten = 1; // XClob is indexed from 1
ISC_STATUS aErr = 0;
sal_Int64 nLen = xClob->length();
- while ( nLen > nCharWritten )
+ while ( nLen >= nCharWritten )
{
- sal_Int64 nCharRemain = nLen - nCharWritten;
+ sal_Int64 nCharRemain = nLen - nCharWritten + 1;
constexpr sal_uInt16 MAX_SIZE = SAL_MAX_UINT16 / 4;
sal_uInt16 nWriteSize = std::min<sal_Int64>(nCharRemain, MAX_SIZE);
OString sData = OUStringToOString(
@@ -660,10 +660,41 @@ void OPreparedStatement::setClob( sal_Int32 nParameterIndex, const OUString& rSt
OString sData = OUStringToOString(
rStr,
RTL_TEXTENCODING_UTF8);
- ISC_STATUS aErr = isc_put_segment( m_statusVector,
+ size_t nDataSize = sData.getLength();
+ ISC_STATUS aErr = 0;
+ // we can't store more than MAX_SIZE_SEGMENT in a segment
+ if (nDataSize <= MAX_SIZE_SEGMENT)
+ {
+ aErr = isc_put_segment( m_statusVector,
&aBlobHandle,
sData.getLength(),
sData.getStr() );
+ }
+ else
+ {
+ // if we need more, let's split the input and first let's calculate the nb of entire chunks needed
+ size_t nNbEntireChunks = nDataSize / MAX_SIZE_SEGMENT;
+ for (size_t i = 0; i < nNbEntireChunks; ++i)
+ {
+ OString strCurrentChunk = sData.copy(i * MAX_SIZE_SEGMENT, MAX_SIZE_SEGMENT);
+ aErr = isc_put_segment( m_statusVector,
+ &aBlobHandle,
+ strCurrentChunk.getLength(),
+ strCurrentChunk.getStr() );
+ if (aErr)
+ break;
+ }
+ size_t nRemainingBytes = nDataSize - (nNbEntireChunks * MAX_SIZE_SEGMENT);
+ if (nRemainingBytes && !aErr)
+ {
+ // then copy the remaining
+ OString strCurrentChunk = sData.copy(nNbEntireChunks * MAX_SIZE_SEGMENT, nRemainingBytes);
+ aErr = isc_put_segment( m_statusVector,
+ &aBlobHandle,
+ strCurrentChunk.getLength(),
+ strCurrentChunk.getStr() );
+ }
+ }
// We need to make sure we close the Blob even if there are errors, hence evaluate
// errors after closing.
@@ -782,7 +813,7 @@ void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, c
sBuffer.append(sValue);
if(sValue.indexOf('.') != -1) // there is a dot
{
- for(sal_Int32 i=sValue.copy(sValue.indexOf('.')+1).getLength(); i<scale;i++)
+ for(sal_Int32 i=sValue.subView(sValue.indexOf('.')+1).size(); i<scale;i++)
{
sBuffer.append('0');
}
@@ -908,7 +939,7 @@ void SAL_CALL OPreparedStatement::setBytes(sal_Int32 nParameterIndex,
{
xBytesCopy.realloc( nMaxSize );
}
- const auto nSize = xBytesCopy.getLength();
+ const sal_uInt16 nSize = xBytesCopy.getLength();
// 8000 corresponds to value from lcl_addDefaultParameters
// in dbaccess/source/filter/hsqldb/createparser.cxx
if (nSize > 8000)
@@ -916,6 +947,7 @@ void SAL_CALL OPreparedStatement::setBytes(sal_Int32 nParameterIndex,
free(pVar->sqldata);
pVar->sqldata = static_cast<char *>(malloc(sizeof(char) * nSize + 2));
}
+ static_assert(sizeof(nSize) == 2, "must match dest memcpy len");
// First 2 bytes indicate string size
memcpy(pVar->sqldata, &nSize, 2);
// Actual data
@@ -923,9 +955,12 @@ void SAL_CALL OPreparedStatement::setBytes(sal_Int32 nParameterIndex,
}
else if( dType == SQL_TEXT )
{
+ if (pVar->sqllen < xBytes.getLength())
+ dbtools::throwSQLException("Data too big for this field",
+ dbtools::StandardSQLState::INVALID_SQL_DATA_TYPE, *this);
setParameterNull(nParameterIndex, false);
memcpy(pVar->sqldata, xBytes.getConstArray(), xBytes.getLength() );
- // Fill remainder with spaces
+ // Fill remainder with zeroes
memset(pVar->sqldata + xBytes.getLength(), 0, pVar->sqllen - xBytes.getLength());
}
else