connectivity/source/drivers/firebird/PreparedStatement.cxx |   35 ++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

New commits:
commit a943e7ddd13315b18d7b33cd1b2f852144f54344
Author:     Julien Nabet <[email protected]>
AuthorDate: Tue Jun 7 22:57:43 2022 +0200
Commit:     Julien Nabet <[email protected]>
CommitDate: Wed Jun 8 21:13:22 2022 +0200

    tdf#149470: Firebird, Clob may need several segments to store a very long 
input
    
    Change-Id: I85c7789f46d834d2ae1b251f915382f833bd529d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135480
    Reviewed-by: Caolán McNamara <[email protected]>
    Reviewed-by: Julien Nabet <[email protected]>
    Tested-by: Jenkins

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.

Reply via email to