summaryrefslogtreecommitdiff
path: root/connectivity
diff options
context:
space:
mode:
authorAndrzej Hunt <andrzej.hunt@collabora.com>2013-12-05 13:58:59 +0000
committerAndrzej Hunt <andrzej.hunt@collabora.com>2014-01-01 19:11:56 +0000
commit990c8f57b673eec03296ca72b19f946775840395 (patch)
tree5eba500826100eafc095ff6c1a3891a17dc5d567 /connectivity
parent273bbd2930736087a6b768c939256ed5d9ddcabc (diff)
fdo#70664 Implement Blob writing (firebird-sdbc).
Change-Id: Ia95c6e1a0ede2103aae25610baeb3c7a9642113a (cherry picked from commit cb4b290bcfbc5ac73103a557f8de429c3d7d7c3b)
Diffstat (limited to 'connectivity')
-rw-r--r--connectivity/source/drivers/firebird/PreparedStatement.cxx128
-rw-r--r--connectivity/source/drivers/firebird/PreparedStatement.hxx8
2 files changed, 126 insertions, 10 deletions
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,