diff options
author | Andrzej J.R. Hunt <andrzej@ahunt.org> | 2013-07-21 17:45:08 +0200 |
---|---|---|
committer | Andrzej J.R. Hunt <andrzej@ahunt.org> | 2013-07-21 18:47:12 +0200 |
commit | 229a9c1ca024958808d7f6decad6213b20862abd (patch) | |
tree | 58653e43b103b31ba3c2f433c74b2a18742278b0 /connectivity | |
parent | 997b440080cccc19e35e8c5e32d24ce6c0861779 (diff) |
Implement the first parts of XBlob. (firebird-sdbc)
Change-Id: Iebb80168ec6fb941ca936834ed2275a598dff55e
Diffstat (limited to 'connectivity')
-rw-r--r-- | connectivity/Library_firebird_sdbc.mk | 1 | ||||
-rw-r--r-- | connectivity/source/drivers/firebird/Blob.cxx | 214 | ||||
-rw-r--r-- | connectivity/source/drivers/firebird/Blob.hxx | 86 | ||||
-rw-r--r-- | connectivity/source/drivers/firebird/FConnection.cxx | 16 | ||||
-rw-r--r-- | connectivity/source/drivers/firebird/FConnection.hxx | 11 | ||||
-rw-r--r-- | connectivity/source/drivers/firebird/FResultSet.cxx | 21 | ||||
-rw-r--r-- | connectivity/source/drivers/firebird/FResultSet.hxx | 5 | ||||
-rw-r--r-- | connectivity/source/drivers/firebird/FStatement.cxx | 2 |
8 files changed, 349 insertions, 7 deletions
diff --git a/connectivity/Library_firebird_sdbc.mk b/connectivity/Library_firebird_sdbc.mk index 0c364c5202df..e884ca879f17 100644 --- a/connectivity/Library_firebird_sdbc.mk +++ b/connectivity/Library_firebird_sdbc.mk @@ -37,6 +37,7 @@ $(eval $(call gb_Library_use_libraries,firebird_sdbc, \ $(eval $(call gb_Library_set_componentfile,firebird_sdbc,connectivity/source/drivers/firebird/firebird_sdbc)) $(eval $(call gb_Library_add_exception_objects,firebird_sdbc,\ + connectivity/source/drivers/firebird/Blob \ connectivity/source/drivers/firebird/FConnection \ connectivity/source/drivers/firebird/FDatabaseMetaData \ connectivity/source/drivers/firebird/FDriver \ diff --git a/connectivity/source/drivers/firebird/Blob.cxx b/connectivity/source/drivers/firebird/Blob.cxx new file mode 100644 index 000000000000..12b2622e05c7 --- /dev/null +++ b/connectivity/source/drivers/firebird/Blob.cxx @@ -0,0 +1,214 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "Blob.hxx" +#include "FConnection.hxx" + +#include "connectivity/dbexception.hxx" + +using namespace ::connectivity::firebird; + +using namespace ::cppu; +using namespace ::osl; + +using namespace ::com::sun::star; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::uno; + +Blob::Blob(isc_db_handle* pDatabaseHandle, + isc_tr_handle* pTransactionHandle, + ISC_QUAD& aBlobID): + Blob_BASE(m_aMutex), + m_pDatabaseHandle(pDatabaseHandle), + m_pTransactionHandle(pTransactionHandle), + m_blobID(aBlobID), + m_blobHandle(0), + m_bBlobOpened(false), + m_blobData(0) +{ +} + +void Blob::ensureBlobIsOpened() + throw(SQLException) +{ + MutexGuard aGuard(m_aMutex); + + if (m_bBlobOpened) + return; + + ISC_STATUS aErr; + aErr = isc_open_blob2(m_statusVector, + m_pDatabaseHandle, + m_pTransactionHandle, + &m_blobHandle, + &m_blobID, + 0, + NULL); + if (aErr) + OConnection::evaluateStatusVector(m_statusVector, + "isc_open_blob2", + *this); + +} + +void SAL_CALL Blob::disposing(void) +{ + MutexGuard aGuard(m_aMutex); + + if (m_bBlobOpened) + { + ISC_STATUS aErr; + aErr = isc_close_blob(m_statusVector, + &m_blobHandle); + if (aErr) + { + try + { + OConnection::evaluateStatusVector(m_statusVector, + "isc_close_blob", + *this); + } + catch (SQLException e) + { + // we cannot throw any exceptions here anyway + SAL_WARN("connectivity.firebird", "isc_close_blob failed\n" << + e.Message); + } + } + } + + Blob_BASE::disposing(); +} + +sal_Int64 SAL_CALL Blob::length() + throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(Blob_BASE::rBHelper.bDisposed); + ensureBlobIsOpened(); + + char aBlobItems[] = { + isc_info_blob_total_length + }; + char aResultBuffer[20]; + + isc_blob_info(m_statusVector, + &m_blobHandle, + sizeof(aBlobItems), + aBlobItems, + sizeof(aResultBuffer), + aResultBuffer); + OConnection::evaluateStatusVector(m_statusVector, + "isc_blob_info", + *this); + if (*aResultBuffer == isc_info_blob_total_length) + { + short aResultLength = (short) isc_vax_integer(aResultBuffer, 2); + return isc_vax_integer(aResultBuffer+2, aResultLength); + } + return 0; +} + +uno::Sequence< sal_Int8 > SAL_CALL Blob::getBytes(sal_Int64 aPosition, sal_Int32 aLength) + throw(SQLException, RuntimeException) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(Blob_BASE::rBHelper.bDisposed); + ensureBlobIsOpened(); + + sal_Int64 aTotalLength = length(); + + if (!(aPosition + aLength < aTotalLength)) + { + throw SQLException("Byte array requested outwith valid range", *this, OUString(), 1, Any() ); + } + + if (aTotalLength != m_blobData.getLength()) + { + m_blobData = uno::Sequence< sal_Int8 >(aTotalLength); + char* pArray = (char*) m_blobData.getArray(); + sal_Int64 aBytesRead = 0; + + unsigned short aLengthRead; // The amount read in in a isc_get_segment call + + ISC_STATUS aErr; + do + { + aErr = isc_get_segment(m_statusVector, + &m_blobHandle, + &aLengthRead, + aTotalLength - aBytesRead, + pArray + aBytesRead); + } + while (aErr == 0 || m_statusVector[1] == isc_segment); + // Denotes either sucessful read, or only part of segment read successfully. + if (aErr) + { + m_blobData = uno::Sequence< sal_Int8 >(0); + OConnection::evaluateStatusVector(m_statusVector, + "isc_get_segment", + *this); + } + } + + if (aLength<aTotalLength) + { + uno::Sequence< sal_Int8 > aRet(aLength); + memcpy(aRet.getArray(), m_blobData.getArray() + aLength, aLength); + return aRet; + } + else + { + return m_blobData; // TODO: subsequence + } +} + +uno::Reference< XInputStream > SAL_CALL Blob::getBinaryStream() + throw(SQLException, RuntimeException) +{ +// MutexGuard aGuard(m_aMutex); +// checkDisposed(Blob_BASE::rBHelper.bDisposed); +// ensureBlobIsOpened(); + + ::dbtools::throwFeatureNotImplementedException("Blob::positionOfBlob", *this); + return NULL; +} + +sal_Int64 SAL_CALL Blob::position(const uno::Sequence< sal_Int8 >& rPattern, + sal_Int64 aStart) + throw(SQLException, RuntimeException) +{ +// MutexGuard aGuard(m_aMutex); +// checkDisposed(Blob_BASE::rBHelper.bDisposed); +// ensureBlobIsOpened(); + + (void) rPattern; + (void) aStart; + ::dbtools::throwFeatureNotImplementedException("Blob::positionOfBlob", *this); + return 0; +} + +sal_Int64 SAL_CALL Blob::positionOfBlob(const uno::Reference< XBlob >& rPattern, + sal_Int64 aStart) + throw(SQLException, RuntimeException) +{ +// MutexGuard aGuard(m_aMutex); +// checkDisposed(Blob_BASE::rBHelper.bDisposed); +// ensureBlobIsOpened(); + + (void) rPattern; + (void) aStart; + ::dbtools::throwFeatureNotImplementedException("Blob::positionOfBlob", *this); + return 0; +} + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
\ No newline at end of file diff --git a/connectivity/source/drivers/firebird/Blob.hxx b/connectivity/source/drivers/firebird/Blob.hxx new file mode 100644 index 000000000000..f4eb792f2edf --- /dev/null +++ b/connectivity/source/drivers/firebird/Blob.hxx @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef CONNECTIVITY_FIREBIRD_BLOB_HXX +#define CONNECTIVITY_FIREBIRD_BLOB_HXX + +#include <ibase.h> + +#include <cppuhelper/compbase1.hxx> + +#include <com/sun/star/sdbc/XBlob.hpp> + +namespace connectivity +{ + namespace firebird + { + typedef ::cppu::WeakComponentImplHelper1< ::com::sun::star::sdbc::XBlob > + Blob_BASE; + + class Blob : + public Blob_BASE + { + protected: + ::osl::Mutex m_aMutex; + + isc_db_handle* m_pDatabaseHandle; + isc_tr_handle* m_pTransactionHandle; + // We store our own copy of the blob id as typically the statement + // manages it's own blob id, and blobs are independent of a statement + // in firebird. + ISC_QUAD m_blobID; + isc_blob_handle m_blobHandle; + + bool m_bBlobOpened; + + ISC_STATUS_ARRAY m_statusVector; + + ::com::sun::star::uno::Sequence< sal_Int8 > m_blobData; + + void ensureBlobIsOpened() + throw(::com::sun::star::sdbc::SQLException); + + public: + Blob(isc_db_handle* pDatabaseHandle, + isc_tr_handle* pTransactionHandle, + ISC_QUAD& aBlobID); + + // ---- XBlob ---------------------------------------------------- + virtual sal_Int64 SAL_CALL + length() + throw(::com::sun::star::sdbc::SQLException, + ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL + getBytes(sal_Int64 aPosition, sal_Int32 aLength) + throw(::com::sun::star::sdbc::SQLException, + ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL + getBinaryStream() + throw(::com::sun::star::sdbc::SQLException, + ::com::sun::star::uno::RuntimeException); + virtual sal_Int64 SAL_CALL + position(const ::com::sun::star::uno::Sequence< sal_Int8 >& rPattern, + sal_Int64 aStart) + throw(::com::sun::star::sdbc::SQLException, + ::com::sun::star::uno::RuntimeException); + virtual sal_Int64 SAL_CALL + positionOfBlob(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob >& rPattern, + sal_Int64 aStart) + throw(::com::sun::star::sdbc::SQLException, + ::com::sun::star::uno::RuntimeException); + + // ---- OComponentHelper ------------------------------------------ + virtual void SAL_CALL disposing(); + }; + } + +} + +#endif //CONNECTIVITY_FIREBIRD_BLOB_HXX +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
\ No newline at end of file diff --git a/connectivity/source/drivers/firebird/FConnection.cxx b/connectivity/source/drivers/firebird/FConnection.cxx index f09663b59b4a..3c05d06ab812 100644 --- a/connectivity/source/drivers/firebird/FConnection.cxx +++ b/connectivity/source/drivers/firebird/FConnection.cxx @@ -285,6 +285,22 @@ void OConnection::construct(const ::rtl::OUString& url, const Sequence< Property IMPLEMENT_SERVICE_INFO(OConnection, "com.sun.star.sdbc.drivers.firebird.OConnection", "com.sun.star.sdbc.Connection") +Reference< XBlob> OConnection::createBlob(ISC_QUAD* pBlobId) + throw(SQLException) +{ + SAL_INFO("connectivity.firebird", "createBlob()"); + MutexGuard aGuard(m_aMutex); + checkDisposed(OConnection_BASE::rBHelper.bDisposed); + + Reference< XBlob > xReturn = new Blob(&m_DBHandler, + &m_transactionHandle, + *pBlobId); + + m_aStatements.push_back(WeakReferenceHelper(xReturn)); + return xReturn; +} + + //----- XConnection ---------------------------------------------------------- Reference< XStatement > SAL_CALL OConnection::createStatement( ) throw(SQLException, RuntimeException) diff --git a/connectivity/source/drivers/firebird/FConnection.hxx b/connectivity/source/drivers/firebird/FConnection.hxx index 7bf25d36f41f..5acaf51aa9e8 100644 --- a/connectivity/source/drivers/firebird/FConnection.hxx +++ b/connectivity/source/drivers/firebird/FConnection.hxx @@ -36,6 +36,8 @@ #ifndef CONNECTIVITY_SCONNECTION_HXX #define CONNECTIVITY_SCONNECTION_HXX +#include "Blob.hxx" + #include <com/sun/star/sdbc/SQLWarning.hpp> #include <com/sun/star/beans/PropertyValue.hpp> #include <com/sun/star/document/DocumentEvent.hpp> @@ -182,6 +184,15 @@ namespace connectivity isc_tr_handle& getTransaction(); /** + * Create a new Blob tied to this connection. Blobs are tied to a + * transaction and not to a statement, hence the connection should + * deal with their management. + */ + ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XBlob> + createBlob(ISC_QUAD* pBlobID) + throw(::com::sun::star::sdbc::SQLException); + + /** * Evaluate a firebird status vector and throw exceptions as necessary. * The content of the status vector is included in the thrown exception. */ diff --git a/connectivity/source/drivers/firebird/FResultSet.cxx b/connectivity/source/drivers/firebird/FResultSet.cxx index b30a141e9244..a234057fc561 100644 --- a/connectivity/source/drivers/firebird/FResultSet.cxx +++ b/connectivity/source/drivers/firebird/FResultSet.cxx @@ -447,7 +447,7 @@ T OResultSet::retrieveValue(sal_Int32 columnIndex) } template <> -OUString OResultSet::retrieveValue<OUString>(sal_Int32 columnIndex) +OUString OResultSet::retrieveValue(sal_Int32 columnIndex) { if ((m_bWasNull = isNull(columnIndex))) return OUString(); @@ -476,6 +476,14 @@ OUString OResultSet::retrieveValue<OUString>(sal_Int32 columnIndex) } } +template <> +ISC_QUAD* OResultSet::retrieveValue(sal_Int32 columnIndex) +{ + if ((m_bWasNull = isNull(columnIndex))) + return 0; + return (ISC_QUAD*) m_pSqlda->sqlvar[columnIndex-1].sqldata; +} + template <typename T> T OResultSet::safelyRetrieveValue(sal_Int32 columnIndex) throw (SQLException) @@ -601,14 +609,17 @@ uno::Reference< XClob > SAL_CALL OResultSet::getClob( sal_Int32 columnIndex ) th return NULL; } -// ------------------------------------------------------------------------- -uno::Reference< XBlob > SAL_CALL OResultSet::getBlob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException) + +uno::Reference< XBlob > SAL_CALL OResultSet::getBlob(sal_Int32 columnIndex) + throw(SQLException, RuntimeException) { - (void) columnIndex; MutexGuard aGuard(m_pConnection->getMutex()); checkDisposed(OResultSet_BASE::rBHelper.bDisposed); - return NULL; + ISC_QUAD* pBlobID = safelyRetrieveValue< ISC_QUAD* >(columnIndex); + if (!pBlobID) + return 0; + return m_pConnection->createBlob(pBlobID); } // ------------------------------------------------------------------------- diff --git a/connectivity/source/drivers/firebird/FResultSet.hxx b/connectivity/source/drivers/firebird/FResultSet.hxx index 011f9ff44338..3b4f734574f0 100644 --- a/connectivity/source/drivers/firebird/FResultSet.hxx +++ b/connectivity/source/drivers/firebird/FResultSet.hxx @@ -243,7 +243,10 @@ namespace connectivity }; // Specialisations have to be in the namespace and can't be within the class. - template <> ::rtl::OUString OResultSet::retrieveValue< ::rtl::OUString >(sal_Int32 columnIndex); + template <> ::rtl::OUString + OResultSet::retrieveValue(sal_Int32 columnIndex); + template <> ISC_QUAD* + OResultSet::retrieveValue(sal_Int32 columnIndex); } } #endif // CONNECTIVITY_SRESULTSET_HXX diff --git a/connectivity/source/drivers/firebird/FStatement.cxx b/connectivity/source/drivers/firebird/FStatement.cxx index 6a81754c9ff5..5ccd0c02da10 100644 --- a/connectivity/source/drivers/firebird/FStatement.cxx +++ b/connectivity/source/drivers/firebird/FStatement.cxx @@ -322,7 +322,7 @@ int OStatement_Base::prepareAndDescribeStatement(const OUString& sqlIn, pVar->sqldata = (char *)malloc(sizeof(time_t)); break; case SQL_BLOB: - assert(false); // We cannot deal with blobs in DSQL + pVar->sqldata = (char*) malloc(sizeof(ISC_QUAD)); break; case SQL_ARRAY: assert(false); // TODO: implement |