From a943e7ddd13315b18d7b33cd1b2f852144f54344 Mon Sep 17 00:00:00 2001 From: Julien Nabet Date: Tue, 7 Jun 2022 22:57:43 +0200 Subject: [PATCH] tdf#149470: Firebird, Clob may need several segments to store a very long input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I85c7789f46d834d2ae1b251f915382f833bd529d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135480 Reviewed-by: Caolán McNamara Reviewed-by: Julien Nabet Tested-by: Jenkins --- .../drivers/firebird/PreparedStatement.cxx | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/connectivity/source/drivers/firebird/PreparedStatement.cxx b/connectivity/source/drivers/firebird/PreparedStatement.cxx index 9cd9157a7d6d..816c38d5c7e3 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) @@ -661,10 +663,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.