From 990c8f57b673eec03296ca72b19f946775840395 Mon Sep 17 00:00:00 2001 From: Andrzej Hunt Date: Thu, 5 Dec 2013 13:58:59 +0000 Subject: fdo#70664 Implement Blob writing (firebird-sdbc). Change-Id: Ia95c6e1a0ede2103aae25610baeb3c7a9642113a (cherry picked from commit cb4b290bcfbc5ac73103a557f8de429c3d7d7c3b) --- .../source/drivers/firebird/PreparedStatement.cxx | 128 +++++++++++++++++++-- .../source/drivers/firebird/PreparedStatement.hxx | 8 ++ 2 files changed, 126 insertions(+), 10 deletions(-) (limited to 'connectivity') diff --git a/connectivity/source/drivers/firebird/PreparedStatement.cxx b/connectivity/source/drivers/firebird/PreparedStatement.cxx index 5e02616e5029..128f35716f76 100644 --- a/connectivity/source/drivers/firebird/PreparedStatement.cxx +++ b/connectivity/source/drivers/firebird/PreparedStatement.cxx @@ -432,6 +432,43 @@ void SAL_CALL OPreparedStatement::setTimestamp(sal_Int32 nIndex, const DateTime& } // ------------------------------------------------------------------------- +// void OPreaparedStatement::set +void OPreparedStatement::openBlobForWriting(isc_blob_handle& rBlobHandle, ISC_QUAD& rBlobId) +{ + ISC_STATUS aErr; + + aErr = isc_create_blob2(m_statusVector, + &m_pConnection->getDBHandle(), + &m_pConnection->getTransaction(), + &rBlobHandle, + &rBlobId, + 0, // Blob parameter buffer length + 0); // Blob parameter buffer handle + + if (aErr) + { + evaluateStatusVector(m_statusVector, + "setBlob failed on " + m_sSqlStatement, + *this); + assert(false); + } +} + +void OPreparedStatement::closeBlobAfterWriting(isc_blob_handle& rBlobHandle) +{ + ISC_STATUS aErr; + + aErr = isc_close_blob(m_statusVector, + &rBlobHandle); + if (aErr) + { + evaluateStatusVector(m_statusVector, + "isc_close_blob failed", + *this); + assert(false); + } +} + void SAL_CALL OPreparedStatement::setClob( sal_Int32 parameterIndex, const Reference< XClob >& x ) throw(SQLException, RuntimeException) { (void) parameterIndex; @@ -440,16 +477,53 @@ void SAL_CALL OPreparedStatement::setClob( sal_Int32 parameterIndex, const Refer checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } -// ------------------------------------------------------------------------- -void SAL_CALL OPreparedStatement::setBlob( sal_Int32 parameterIndex, const Reference< XBlob >& x ) throw(SQLException, RuntimeException) +void SAL_CALL OPreparedStatement::setBlob(sal_Int32 nParameterIndex, + const Reference< XBlob >& xBlob) + throw (SQLException, RuntimeException) { - (void) parameterIndex; - (void) x; - ::osl::MutexGuard aGuard( m_aMutex ); + ::osl::MutexGuard aGuard(m_aMutex); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); + isc_blob_handle aBlobHandle = 0; + ISC_QUAD aBlobId; + + openBlobForWriting(aBlobHandle, aBlobId); + + // Max segment size is 2^16 == SAL_MAX_UINT16 + sal_uInt64 nDataWritten = 0; + ISC_STATUS aErr; + while (xBlob->length() - nDataWritten > 0) + { + sal_uInt64 nDataRemaining = xBlob->length() - nDataWritten; + sal_uInt16 nWriteSize = (nDataRemaining > SAL_MAX_UINT16) ? SAL_MAX_UINT16 : nDataRemaining; + aErr = isc_put_segment(m_statusVector, + &aBlobHandle, + nWriteSize, + (const char*) xBlob->getBytes(nDataWritten, nWriteSize).getConstArray()); + nDataWritten += nWriteSize; + + + if (aErr) + break; + + } + + // We need to make sure we close the Blob even if their are errors, hence evaluate + // errors after closing. + closeBlobAfterWriting(aBlobHandle); + + if (aErr) + { + evaluateStatusVector(m_statusVector, + "isc_put_segment failed", + *this); + assert(false); + } + + setValue< ISC_QUAD >(nParameterIndex, aBlobId, SQL_BLOB); } + // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setArray( sal_Int32 parameterIndex, const Reference< XArray >& x ) throw(SQLException, RuntimeException) @@ -503,15 +577,49 @@ void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); } -// ------------------------------------------------------------------------- -void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException) +void SAL_CALL OPreparedStatement::setBytes(sal_Int32 nParameterIndex, + const Sequence< sal_Int8 >& xBytes) + throw (SQLException, RuntimeException) { - (void) parameterIndex; - (void) x; - ::osl::MutexGuard aGuard( m_aMutex ); + ::osl::MutexGuard aGuard(m_aMutex); checkDisposed(OStatementCommonBase_Base::rBHelper.bDisposed); + isc_blob_handle aBlobHandle = 0; + ISC_QUAD aBlobId; + + openBlobForWriting(aBlobHandle, aBlobId); + + // Max segment size is 2^16 == SAL_MAX_UINT16 + sal_uInt64 nDataWritten = 0; + ISC_STATUS aErr; + while (xBytes.getLength() - nDataWritten > 0) + { + sal_uInt64 nDataRemaining = xBytes.getLength() - nDataWritten; + sal_uInt16 nWriteSize = (nDataRemaining > SAL_MAX_UINT16) ? SAL_MAX_UINT16 : nDataRemaining; + aErr = isc_put_segment(m_statusVector, + &aBlobHandle, + nWriteSize, + (const char*) xBytes.getConstArray() + nDataWritten); + nDataWritten += nWriteSize; + + if (aErr) + break; + } + + // We need to make sure we close the Blob even if their are errors, hence evaluate + // errors after closing. + closeBlobAfterWriting(aBlobHandle); + + if (aErr) + { + evaluateStatusVector(m_statusVector, + "isc_put_segment failed", + *this); + assert(false); + } + + setValue< ISC_QUAD >(nParameterIndex, aBlobId, SQL_BLOB); } // ------------------------------------------------------------------------- diff --git a/connectivity/source/drivers/firebird/PreparedStatement.hxx b/connectivity/source/drivers/firebird/PreparedStatement.hxx index d052b7ee4b0f..ea1bb0590cd3 100644 --- a/connectivity/source/drivers/firebird/PreparedStatement.hxx +++ b/connectivity/source/drivers/firebird/PreparedStatement.hxx @@ -87,6 +87,14 @@ namespace connectivity void ensurePrepared() throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); + /** + * Assumes that all necessary mutexes have been taken. + */ + void openBlobForWriting(isc_blob_handle& rBlobHandle, ISC_QUAD& rBlobId); + /** + * Assumes that all necessary mutexes have been taken. + */ + void closeBlobAfterWriting(isc_blob_handle& rBlobHandle); protected: virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, -- cgit v1.2.3