summaryrefslogtreecommitdiff
path: root/connectivity
diff options
context:
space:
mode:
authorAndrzej J.R. Hunt <andrzej@ahunt.org>2013-07-21 17:45:08 +0200
committerAndrzej J.R. Hunt <andrzej@ahunt.org>2013-07-21 18:47:12 +0200
commit229a9c1ca024958808d7f6decad6213b20862abd (patch)
tree58653e43b103b31ba3c2f433c74b2a18742278b0 /connectivity
parent997b440080cccc19e35e8c5e32d24ce6c0861779 (diff)
Implement the first parts of XBlob. (firebird-sdbc)
Change-Id: Iebb80168ec6fb941ca936834ed2275a598dff55e
Diffstat (limited to 'connectivity')
-rw-r--r--connectivity/Library_firebird_sdbc.mk1
-rw-r--r--connectivity/source/drivers/firebird/Blob.cxx214
-rw-r--r--connectivity/source/drivers/firebird/Blob.hxx86
-rw-r--r--connectivity/source/drivers/firebird/FConnection.cxx16
-rw-r--r--connectivity/source/drivers/firebird/FConnection.hxx11
-rw-r--r--connectivity/source/drivers/firebird/FResultSet.cxx21
-rw-r--r--connectivity/source/drivers/firebird/FResultSet.hxx5
-rw-r--r--connectivity/source/drivers/firebird/FStatement.cxx2
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