1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 #include "Connection.hxx"
14 #include <com/sun/star/lang/IllegalArgumentException.hpp>
15 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
16 #include <connectivity/dbexception.hxx>
17 #include <cppuhelper/exc_hlp.hxx>
19 using namespace ::connectivity::firebird
;
21 using namespace ::cppu
;
22 using namespace ::osl
;
24 using namespace ::com::sun::star
;
25 using namespace ::com::sun::star::io
;
26 using namespace ::com::sun::star::sdbc
;
27 using namespace ::com::sun::star::uno
;
29 Blob::Blob(isc_db_handle
* pDatabaseHandle
,
30 isc_tr_handle
* pTransactionHandle
,
33 m_pDatabaseHandle(pDatabaseHandle
),
34 m_pTransactionHandle(pTransactionHandle
),
36 #if SAL_TYPES_SIZEOFPOINTER == 8
39 m_blobHandle(nullptr),
47 void Blob::ensureBlobIsOpened()
50 MutexGuard
aGuard(m_aMutex
);
56 aErr
= isc_open_blob2(m_statusVector
,
65 evaluateStatusVector(m_statusVector
, "isc_open_blob2", *this);
71 isc_info_blob_total_length
73 char aResultBuffer
[20];
75 isc_blob_info(m_statusVector
,
79 sizeof(aResultBuffer
),
83 evaluateStatusVector(m_statusVector
, "isc_blob_info", *this);
85 if (*aResultBuffer
== isc_info_blob_total_length
)
87 short aResultLength
= (short) isc_vax_integer(aResultBuffer
+1, 2);
88 m_nBlobLength
= isc_vax_integer(aResultBuffer
+3, aResultLength
);
96 void Blob::closeBlob()
99 MutexGuard
aGuard(m_aMutex
);
104 aErr
= isc_close_blob(m_statusVector
,
107 evaluateStatusVector(m_statusVector
, "isc_close_blob", *this);
109 m_bBlobOpened
= false;
110 #if SAL_TYPES_SIZEOFPOINTER == 8
113 m_blobHandle
= nullptr;
118 void SAL_CALL
Blob::disposing()
124 catch (SQLException
&e
)
126 // we cannot throw any exceptions here...
127 SAL_WARN("connectivity.firebird", "isc_close_blob failed\n" <<
131 Blob_BASE::disposing();
134 sal_Int64 SAL_CALL
Blob::length()
135 throw(SQLException
, RuntimeException
, std::exception
)
137 MutexGuard
aGuard(m_aMutex
);
138 checkDisposed(Blob_BASE::rBHelper
.bDisposed
);
139 ensureBlobIsOpened();
141 return m_nBlobLength
;
144 uno::Sequence
< sal_Int8
> SAL_CALL
Blob::getBytes(sal_Int64 nPosition
,
146 throw(SQLException
, RuntimeException
, std::exception
)
148 MutexGuard
aGuard(m_aMutex
);
149 checkDisposed(Blob_BASE::rBHelper
.bDisposed
);
150 ensureBlobIsOpened();
152 if (nPosition
> m_nBlobLength
)
153 throw lang::IllegalArgumentException("nPosition out of range", *this, 0);
154 // We only have to read as many bytes as are available, i.e. nPosition+nBytes
155 // can legally be greater than the total length, hence we don't bother to check.
157 if (nPosition
> m_nBlobPosition
)
159 // Resets to the beginning (we can't seek these blobs)
161 ensureBlobIsOpened();
164 skipBytes(nPosition
- m_nBlobPosition
);
166 // Don't bother preallocating: readBytes does the appropriate calculations
167 // and reallocates for us.
168 uno::Sequence
< sal_Int8
> aBytes
;
169 readBytes(aBytes
, nBytes
);
173 uno::Reference
< XInputStream
> SAL_CALL
Blob::getBinaryStream()
174 throw(SQLException
, RuntimeException
, std::exception
)
179 sal_Int64 SAL_CALL
Blob::position(const uno::Sequence
< sal_Int8
>& /*rPattern*/,
180 sal_Int64
/*nStart*/)
181 throw(SQLException
, RuntimeException
, std::exception
)
183 ::dbtools::throwFeatureNotImplementedSQLException("Blob::position", *this);
187 sal_Int64 SAL_CALL
Blob::positionOfBlob(const uno::Reference
< XBlob
>& /*rPattern*/,
188 sal_Int64
/*aStart*/)
189 throw(SQLException
, RuntimeException
, std::exception
)
191 ::dbtools::throwFeatureNotImplementedSQLException("Blob::positionOfBlob", *this);
195 // ---- XInputStream ----------------------------------------------------------
197 sal_Int32 SAL_CALL
Blob::readBytes(uno::Sequence
< sal_Int8
>& rDataOut
,
199 throw (NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
, std::exception
)
201 MutexGuard
aGuard(m_aMutex
);
205 checkDisposed(Blob_BASE::rBHelper
.bDisposed
);
206 ensureBlobIsOpened();
208 catch (const NotConnectedException
&)
212 catch (const BufferSizeExceededException
&)
216 catch (const IOException
&)
220 catch (const RuntimeException
&)
224 catch (const Exception
& e
)
226 css::uno::Any
a(cppu::getCaughtException());
227 throw css::lang::WrappedTargetRuntimeException(
228 "wrapped Exception " + e
.Message
,
229 css::uno::Reference
<css::uno::XInterface
>(), a
);
232 // Ensure we have enough space for the amount of data we can actually read.
233 const sal_Int64 nBytesAvailable
= m_nBlobLength
- m_nBlobPosition
;
234 const sal_Int32 nBytesToRead
= nBytes
< nBytesAvailable
? nBytes
: nBytesAvailable
;
236 if (rDataOut
.getLength() < nBytesToRead
)
237 rDataOut
.realloc(nBytesToRead
);
239 sal_Int32 nTotalBytesRead
= 0;
241 while (nTotalBytesRead
< nBytesToRead
)
243 sal_uInt16 nBytesRead
= 0;
244 sal_uInt64 nDataRemaining
= nBytesToRead
- nTotalBytesRead
;
245 sal_uInt16 nReadSize
= (nDataRemaining
> SAL_MAX_UINT16
) ? SAL_MAX_UINT16
: nDataRemaining
;
246 aErr
= isc_get_segment(m_statusVector
,
250 reinterpret_cast<char*>(rDataOut
.getArray()) + nTotalBytesRead
);
251 if (aErr
&& IndicatesError(m_statusVector
))
253 OUString
sError(StatusVectorToString(m_statusVector
, "isc_get_segment"));
254 throw IOException(sError
, *this);
256 nTotalBytesRead
+= nBytesRead
;
257 m_nBlobPosition
+= nBytesRead
;
260 return nTotalBytesRead
;
263 sal_Int32 SAL_CALL
Blob::readSomeBytes(uno::Sequence
< sal_Int8
>& rDataOut
,
264 sal_Int32 nMaximumBytes
)
265 throw (NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
, std::exception
)
267 // We don't have any way of verifying how many bytes are immediately available,
268 // hence we just pass through direct to readBytes
269 // (Spec: "reads the available number of bytes, at maximum nMaxBytesToRead.")
270 return readBytes(rDataOut
, nMaximumBytes
);
273 void SAL_CALL
Blob::skipBytes(sal_Int32 nBytesToSkip
)
274 throw (NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
, std::exception
)
276 // There is no way of directly skipping, hence we have to pretend to skip
277 // by reading & discarding the data.
278 uno::Sequence
< sal_Int8
> aBytes
;
279 readBytes(aBytes
, nBytesToSkip
);
282 sal_Int32 SAL_CALL
Blob::available()
283 throw (NotConnectedException
, IOException
, RuntimeException
, std::exception
)
285 MutexGuard
aGuard(m_aMutex
);
289 checkDisposed(Blob_BASE::rBHelper
.bDisposed
);
290 ensureBlobIsOpened();
292 catch (const NotConnectedException
&)
296 catch (const IOException
&)
300 catch (const RuntimeException
&)
304 catch (const Exception
& e
)
306 css::uno::Any
a(cppu::getCaughtException());
307 throw css::lang::WrappedTargetRuntimeException(
308 "wrapped Exception " + e
.Message
,
309 css::uno::Reference
<css::uno::XInterface
>(), a
);
312 return m_nBlobLength
- m_nBlobPosition
;
315 void SAL_CALL
Blob::closeInput()
316 throw(NotConnectedException
, IOException
, RuntimeException
, std::exception
)
322 catch (const NotConnectedException
&)
326 catch (const IOException
&)
330 catch (const RuntimeException
&)
334 catch (const Exception
& e
)
336 css::uno::Any
a(cppu::getCaughtException());
337 throw css::lang::WrappedTargetRuntimeException(
338 "wrapped Exception " + e
.Message
,
339 css::uno::Reference
<css::uno::XInterface
>(), a
);
343 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */