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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "ResultSet.hxx"
21 #include "ResultSetMetaData.hxx"
24 #include <comphelper/sequence.hxx>
25 #include <cppuhelper/typeprovider.hxx>
26 #include <cppuhelper/supportsservice.hxx>
27 #include <connectivity/dbexception.hxx>
28 #include <propertyids.hxx>
29 #include <rtl/string.hxx>
30 #include <rtl/ustrbuf.hxx>
32 #include <TConnection.hxx>
34 #include <com/sun/star/beans/PropertyAttribute.hpp>
35 #include <com/sun/star/lang/DisposedException.hpp>
36 #include <com/sun/star/sdbc/DataType.hpp>
37 #include <com/sun/star/sdbcx/CompareBookmark.hpp>
39 using namespace ::comphelper
;
40 using namespace ::connectivity
;
41 using namespace ::connectivity::firebird
;
42 using namespace ::cppu
;
43 using namespace ::dbtools
;
44 using namespace ::osl
;
46 using namespace ::com::sun::star
;
47 using namespace ::com::sun::star::uno
;
48 using namespace ::com::sun::star::lang
;
49 using namespace ::com::sun::star::beans
;
50 using namespace ::com::sun::star::sdbc
;
51 using namespace ::com::sun::star::sdbcx
;
52 using namespace ::com::sun::star::container
;
53 using namespace ::com::sun::star::io
;
54 using namespace ::com::sun::star::util
;
56 OResultSet::OResultSet(Connection
* pConnection
,
58 const uno::Reference
< XInterface
>& xStatement
,
59 isc_stmt_handle
& aStatementHandle
,
61 : OResultSet_BASE(rMutex
)
62 , OPropertyContainer(OResultSet_BASE::rBHelper
)
63 , m_bIsBookmarkable(false)
65 , m_nResultSetType(css::sdbc::ResultSetType::FORWARD_ONLY
)
66 , m_nFetchDirection(css::sdbc::FetchDirection::FORWARD
)
67 , m_nResultSetConcurrency(css::sdbc::ResultSetConcurrency::READ_ONLY
)
68 , m_pConnection(pConnection
)
70 , m_xStatement(xStatement
)
71 , m_xMetaData(nullptr)
73 , m_statementHandle(aStatementHandle
)
76 , m_bIsAfterLastRow(false)
77 , m_fieldCount(pSqlda
? pSqlda
->sqld
: 0)
79 SAL_INFO("connectivity.firebird", "OResultSet().");
80 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISBOOKMARKABLE
),
81 PROPERTY_ID_ISBOOKMARKABLE
,
82 PropertyAttribute::READONLY
,
84 cppu::UnoType
<decltype(m_bIsBookmarkable
)>::get());
85 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE
),
86 PROPERTY_ID_FETCHSIZE
,
87 PropertyAttribute::READONLY
,
89 cppu::UnoType
<decltype(m_nFetchSize
)>::get());
90 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE
),
91 PROPERTY_ID_RESULTSETTYPE
,
92 PropertyAttribute::READONLY
,
94 cppu::UnoType
<decltype(m_nResultSetType
)>::get());
95 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION
),
96 PROPERTY_ID_FETCHDIRECTION
,
97 PropertyAttribute::READONLY
,
99 cppu::UnoType
<decltype(m_nFetchDirection
)>::get());
100 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY
),
101 PROPERTY_ID_RESULTSETCONCURRENCY
,
102 PropertyAttribute::READONLY
,
103 &m_nResultSetConcurrency
,
104 cppu::UnoType
<decltype(m_nResultSetConcurrency
)>::get());
107 return; // TODO: what?
111 OResultSet::~OResultSet()
115 // ---- XResultSet -- Row retrieval methods ------------------------------------
116 sal_Int32 SAL_CALL
OResultSet::getRow() throw(SQLException
, RuntimeException
, std::exception
)
118 MutexGuard
aGuard(m_rMutex
);
119 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
124 sal_Bool SAL_CALL
OResultSet::next() throw(SQLException
, RuntimeException
, std::exception
)
126 MutexGuard
aGuard(m_rMutex
);
127 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
131 ISC_STATUS fetchStat
= isc_dsql_fetch(m_statusVector
,
135 if (fetchStat
== 0) // SUCCESSFUL
139 else if (fetchStat
== 100) // END OF DATASET
141 m_bIsAfterLastRow
= true;
146 SAL_WARN("connectivity.firebird", "Error when fetching data");
147 // Throws sql exception as appropriate
148 evaluateStatusVector(m_statusVector
, "isc_dsql_fetch", *this);
153 sal_Bool SAL_CALL
OResultSet::previous() throw(SQLException
, RuntimeException
, std::exception
)
155 ::dbtools::throwFunctionNotSupportedSQLException("previous not supported in firebird",
160 sal_Bool SAL_CALL
OResultSet::isLast() throw(SQLException
, RuntimeException
, std::exception
)
162 ::dbtools::throwFunctionNotSupportedSQLException("isLast not supported in firebird",
167 sal_Bool SAL_CALL
OResultSet::isBeforeFirst() throw(SQLException
, RuntimeException
, std::exception
)
169 MutexGuard
aGuard(m_rMutex
);
170 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
172 return m_currentRow
== 0;
175 sal_Bool SAL_CALL
OResultSet::isAfterLast() throw(SQLException
, RuntimeException
, std::exception
)
177 MutexGuard
aGuard(m_rMutex
);
178 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
180 return m_bIsAfterLastRow
;
183 sal_Bool SAL_CALL
OResultSet::isFirst() throw(SQLException
, RuntimeException
, std::exception
)
185 MutexGuard
aGuard(m_rMutex
);
186 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
188 return m_currentRow
== 1 && !m_bIsAfterLastRow
;
191 void SAL_CALL
OResultSet::beforeFirst() throw(SQLException
, RuntimeException
, std::exception
)
193 MutexGuard
aGuard(m_rMutex
);
194 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
196 if (m_currentRow
!= 0)
197 ::dbtools::throwFunctionNotSupportedSQLException("beforeFirst not supported in firebird",
201 void SAL_CALL
OResultSet::afterLast() throw(SQLException
, RuntimeException
, std::exception
)
203 MutexGuard
aGuard(m_rMutex
);
204 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
206 if (!m_bIsAfterLastRow
)
207 ::dbtools::throwFunctionNotSupportedSQLException("afterLast not supported in firebird",
211 sal_Bool SAL_CALL
OResultSet::first() throw(SQLException
, RuntimeException
, std::exception
)
213 MutexGuard
aGuard(m_rMutex
);
214 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
216 if (m_currentRow
== 0)
220 else if (m_currentRow
== 1 && !m_bIsAfterLastRow
)
226 ::dbtools::throwFunctionNotSupportedSQLException("first not supported in firebird",
232 sal_Bool SAL_CALL
OResultSet::last() throw(SQLException
, RuntimeException
, std::exception
)
234 // We need to iterate past the last row to know when we've passed the last
235 // row, hence we can't actually move to last.
236 ::dbtools::throwFunctionNotSupportedSQLException("last not supported in firebird",
241 sal_Bool SAL_CALL
OResultSet::absolute(sal_Int32 aRow
) throw(SQLException
, RuntimeException
, std::exception
)
243 MutexGuard
aGuard(m_rMutex
);
244 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
246 if (aRow
> m_currentRow
)
248 sal_Int32 aIterations
= aRow
- m_currentRow
;
249 return relative(aIterations
);
253 ::dbtools::throwFunctionNotSupportedSQLException("absolute not supported in firebird",
259 sal_Bool SAL_CALL
OResultSet::relative(sal_Int32 row
) throw(SQLException
, RuntimeException
, std::exception
)
261 MutexGuard
aGuard(m_rMutex
);
262 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
275 ::dbtools::throwFunctionNotSupportedSQLException("relative not supported in firebird",
281 void SAL_CALL
OResultSet::checkColumnIndex(sal_Int32 nIndex
)
282 throw (SQLException
, RuntimeException
)
284 MutexGuard
aGuard(m_rMutex
);
285 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
287 if( nIndex
< 1 || nIndex
> m_fieldCount
)
289 ::dbtools::throwSQLException(
290 "No column " + OUString::number(nIndex
),
291 ::dbtools::StandardSQLState::COLUMN_NOT_FOUND
,
296 void SAL_CALL
OResultSet::checkRowIndex()
297 throw (SQLException
, RuntimeException
)
299 MutexGuard
aGuard(m_rMutex
);
300 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
302 if((m_currentRow
< 1) || m_bIsAfterLastRow
)
304 ::dbtools::throwSQLException(
306 ::dbtools::StandardSQLState::INVALID_CURSOR_POSITION
,
311 Any SAL_CALL
OResultSet::queryInterface( const Type
& rType
) throw(RuntimeException
, std::exception
)
313 Any aRet
= OPropertySetHelper::queryInterface(rType
);
314 return aRet
.hasValue() ? aRet
: OResultSet_BASE::queryInterface(rType
);
317 Sequence
< Type
> SAL_CALL
OResultSet::getTypes() throw( RuntimeException
, std::exception
)
319 return concatSequences(OPropertySetHelper::getTypes(), OResultSet_BASE::getTypes());
321 // ---- XColumnLocate ---------------------------------------------------------
322 sal_Int32 SAL_CALL
OResultSet::findColumn(const OUString
& rColumnName
)
323 throw(SQLException
, RuntimeException
, std::exception
)
325 MutexGuard
aGuard(m_rMutex
);
326 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
328 uno::Reference
< XResultSetMetaData
> xMeta
= getMetaData();
329 sal_Int32 nLen
= xMeta
->getColumnCount();
332 for(i
= 1; i
<=nLen
; ++i
)
334 // We assume case sensitive, otherwise you'd have to test
335 // xMeta->isCaseSensitive and use qualsIgnoreAsciiCase as needed.
336 if (rColumnName
== xMeta
->getColumnName(i
))
340 ::dbtools::throwInvalidColumnException(rColumnName
, *this);
342 return 0; // Never reached
345 uno::Reference
< XInputStream
> SAL_CALL
OResultSet::getBinaryStream( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
348 MutexGuard
aGuard(m_rMutex
);
349 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
354 uno::Reference
< XInputStream
> SAL_CALL
OResultSet::getCharacterStream( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
357 MutexGuard
aGuard(m_rMutex
);
358 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
363 // ---- Internal Utilities ---------------------------------------------------
364 bool OResultSet::isNull(const sal_Int32 nColumnIndex
)
366 assert(nColumnIndex
<= m_fieldCount
);
367 XSQLVAR
* pVar
= m_pSqlda
->sqlvar
;
369 if (pVar
[nColumnIndex
-1].sqltype
& 1) // Indicates column may contain null
371 if (*pVar
[nColumnIndex
-1].sqlind
== -1)
377 template <typename T
>
378 OUString
OResultSet::makeNumericString(const sal_Int32 nColumnIndex
)
380 // minus because firebird stores scale as a negative number
381 int nDecimalCount
= -(m_pSqlda
->sqlvar
[nColumnIndex
-1].sqlscale
);
382 if(nDecimalCount
< 0)
384 // scale should be always positive
389 OUStringBuffer sRetBuffer
;
390 T nAllDigits
= *reinterpret_cast<T
*>(m_pSqlda
->sqlvar
[nColumnIndex
-1].sqldata
);
391 sal_Int64 nDecimalCountExp
= pow10Integer(nDecimalCount
);
395 sRetBuffer
.append('-');
396 nAllDigits
= -nAllDigits
; // abs
399 sRetBuffer
.append(static_cast<sal_Int64
>(nAllDigits
/ nDecimalCountExp
) );
400 if( nDecimalCount
> 0)
402 sRetBuffer
.append('.');
404 sal_Int64 nFractionalPart
= nAllDigits
% nDecimalCountExp
;
406 int iCount
= 0; // digit count
407 sal_Int64 nFracTemp
= nFractionalPart
;
414 int nMissingNulls
= nDecimalCount
- iCount
;
416 // append nulls after dot and before nFractionalPart
417 for(int i
=0; i
<nMissingNulls
; i
++)
419 sRetBuffer
.append('0');
423 sRetBuffer
.append(nFractionalPart
);
426 return sRetBuffer
.makeStringAndClear();
429 template <typename T
>
430 T
OResultSet::retrieveValue(const sal_Int32 nColumnIndex
, const ISC_SHORT nType
)
432 if ((m_bWasNull
= isNull(nColumnIndex
)))
435 if ((m_pSqlda
->sqlvar
[nColumnIndex
-1].sqltype
& ~1) == nType
)
436 return *reinterpret_cast<T
*>(m_pSqlda
->sqlvar
[nColumnIndex
-1].sqldata
);
438 return retrieveValue
< ORowSetValue
>(nColumnIndex
, 0);
442 ORowSetValue
OResultSet::retrieveValue(const sal_Int32 nColumnIndex
, const ISC_SHORT
/*nType*/)
444 // See http://wiki.openoffice.org/wiki/Documentation/DevGuide/Database/Using_the_getXXX_Methods
445 // (bottom of page) for a chart of possible conversions, we should allow all
446 // of these -- Blob/Clob will probably need some specialist handling especially
447 // w.r.t. to generating Strings for them.
449 // Basically we just have to map to the correct direct request and
450 // ORowSetValue does the rest for us here.
451 int nSqlSubType
= m_pSqlda
->sqlvar
[nColumnIndex
-1].sqlsubtype
;
452 switch (m_pSqlda
->sqlvar
[nColumnIndex
-1].sqltype
& ~1)
456 return getString(nColumnIndex
);
458 if(nSqlSubType
== 1 || nSqlSubType
== 2) //numeric or decimal
459 return getString(nColumnIndex
);
460 return getShort(nColumnIndex
);
462 if(nSqlSubType
== 1 || nSqlSubType
== 2) //numeric or decimal
463 return getString(nColumnIndex
);
464 return getInt(nColumnIndex
);
466 return getFloat(nColumnIndex
);
468 if(nSqlSubType
== 1 || nSqlSubType
== 2) //numeric or decimal
469 return getString(nColumnIndex
);
470 return getDouble(nColumnIndex
);
472 return getFloat(nColumnIndex
);
474 return getTimestamp(nColumnIndex
);
476 return getTime(nColumnIndex
);
478 return getDate(nColumnIndex
);
480 if(nSqlSubType
== 1 || nSqlSubType
== 2) //numeric or decimal
481 return getString(nColumnIndex
);
482 return getLong(nColumnIndex
);
487 // TODO: these are all invalid conversions, so maybe we should
488 // throw an exception?
489 return ORowSetValue();
492 return ORowSetValue();
497 Date
OResultSet::retrieveValue(const sal_Int32 nColumnIndex
, const ISC_SHORT
/*nType*/)
499 if ((m_pSqlda
->sqlvar
[nColumnIndex
-1].sqltype
& ~1) == SQL_TYPE_DATE
)
501 ISC_DATE aISCDate
= *(reinterpret_cast<ISC_DATE
*>(m_pSqlda
->sqlvar
[nColumnIndex
-1].sqldata
));
504 isc_decode_sql_date(&aISCDate
, &aCTime
);
506 return Date(aCTime
.tm_mday
, aCTime
.tm_mon
+ 1, aCTime
.tm_year
+ 1900);
510 return retrieveValue
< ORowSetValue
>(nColumnIndex
, 0);
515 Time
OResultSet::retrieveValue(const sal_Int32 nColumnIndex
, const ISC_SHORT
/*nType*/)
517 if ((m_pSqlda
->sqlvar
[nColumnIndex
-1].sqltype
& ~1) == SQL_TYPE_TIME
)
519 ISC_TIME aISCTime
= *(reinterpret_cast<ISC_TIME
*>(m_pSqlda
->sqlvar
[nColumnIndex
-1].sqldata
));
522 isc_decode_sql_time(&aISCTime
, &aCTime
);
524 // first field is nanoseconds -- not supported in firebird or struct tm.
525 // last field denotes UTC (true) or unknown (false)
526 return Time(0, aCTime
.tm_sec
, aCTime
.tm_min
, aCTime
.tm_hour
, false);
530 return retrieveValue
< ORowSetValue
>(nColumnIndex
, 0);
535 DateTime
OResultSet::retrieveValue(const sal_Int32 nColumnIndex
, const ISC_SHORT
/*nType*/)
537 if ((m_pSqlda
->sqlvar
[nColumnIndex
-1].sqltype
& ~1) == SQL_TIMESTAMP
)
539 ISC_TIMESTAMP aISCTimestamp
= *(reinterpret_cast<ISC_TIMESTAMP
*>(m_pSqlda
->sqlvar
[nColumnIndex
-1].sqldata
));
542 isc_decode_timestamp(&aISCTimestamp
, &aCTime
);
544 return DateTime(0, //nanoseconds, not supported
549 aCTime
.tm_mon
+ 1, // tm is from 0 to 11
550 aCTime
.tm_year
+ 1900, //tm_year is the years since 1900
551 false); // denotes UTC (true), or unknown (false)
555 return retrieveValue
< ORowSetValue
>(nColumnIndex
, 0);
560 OUString
OResultSet::retrieveValue(const sal_Int32 nColumnIndex
, const ISC_SHORT
/*nType*/)
562 // &~1 to remove the "can contain NULL" indicator
563 int aSqlType
= m_pSqlda
->sqlvar
[nColumnIndex
-1].sqltype
& ~1;
564 int aSqlSubType
= m_pSqlda
->sqlvar
[nColumnIndex
-1].sqlsubtype
;
565 if (aSqlType
== SQL_TEXT
)
567 return OUString(m_pSqlda
->sqlvar
[nColumnIndex
-1].sqldata
,
568 m_pSqlda
->sqlvar
[nColumnIndex
-1].sqllen
,
569 RTL_TEXTENCODING_UTF8
);
571 else if (aSqlType
== SQL_VARYING
)
573 // First 2 bytes are a short containing the length of the string
574 // No idea if sqllen is still valid here?
575 sal_uInt16 aLength
= *(reinterpret_cast<sal_uInt16
*>(m_pSqlda
->sqlvar
[nColumnIndex
-1].sqldata
));
576 return OUString(m_pSqlda
->sqlvar
[nColumnIndex
-1].sqldata
+ 2,
578 RTL_TEXTENCODING_UTF8
);
580 else if ((aSqlType
== SQL_SHORT
|| aSqlType
== SQL_LONG
581 || aSqlType
== SQL_DOUBLE
|| aSqlType
== SQL_INT64
)
582 && (aSqlSubType
== 1 || aSqlSubType
== 2))
584 // decimal and numeric types
588 return makeNumericString
<sal_Int16
>(nColumnIndex
);
590 return makeNumericString
<sal_Int32
>(nColumnIndex
);
592 // TODO FIXME 64 bits?
594 return makeNumericString
<sal_Int64
>(nColumnIndex
);
597 return OUString(); // never reached
602 return retrieveValue
< ORowSetValue
>(nColumnIndex
, 0);
607 ISC_QUAD
* OResultSet::retrieveValue(const sal_Int32 nColumnIndex
, const ISC_SHORT nType
)
609 // TODO: this is probably wrong
610 if ((m_pSqlda
->sqlvar
[nColumnIndex
-1].sqltype
& ~1) == nType
)
611 return reinterpret_cast<ISC_QUAD
*>(m_pSqlda
->sqlvar
[nColumnIndex
-1].sqldata
);
613 throw SQLException(); // TODO: better exception (can't convert Blob)
616 template <typename T
>
617 T
OResultSet::safelyRetrieveValue(const sal_Int32 nColumnIndex
, const ISC_SHORT nType
)
619 MutexGuard
aGuard(m_rMutex
);
620 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
622 checkColumnIndex(nColumnIndex
);
625 if ((m_bWasNull
= isNull(nColumnIndex
)))
628 return retrieveValue
< T
>(nColumnIndex
, nType
);
631 // ---- XRow -----------------------------------------------------------------
632 sal_Bool SAL_CALL
OResultSet::wasNull() throw(SQLException
, RuntimeException
, std::exception
)
634 MutexGuard
aGuard(m_rMutex
);
635 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
640 // ---- XRow: Simple Numerical types ------------------------------------------
641 sal_Bool SAL_CALL
OResultSet::getBoolean(sal_Int32 nColumnIndex
)
642 throw(SQLException
, RuntimeException
, std::exception
)
644 // Not a native firebird type hence we always have to convert.
645 return safelyRetrieveValue
< ORowSetValue
>(nColumnIndex
);
648 sal_Int8 SAL_CALL
OResultSet::getByte(sal_Int32 nColumnIndex
)
649 throw(SQLException
, RuntimeException
, std::exception
)
651 // Not a native firebird type hence we always have to convert.
652 return safelyRetrieveValue
< ORowSetValue
>(nColumnIndex
);
655 Sequence
< sal_Int8
> SAL_CALL
OResultSet::getBytes(sal_Int32 columnIndex
)
656 throw(SQLException
, RuntimeException
, std::exception
)
659 return Sequence
< sal_Int8
>(); // TODO: implement
660 //return safelyRetrieveValue(columnIndex);
663 sal_Int16 SAL_CALL
OResultSet::getShort(sal_Int32 columnIndex
)
664 throw(SQLException
, RuntimeException
, std::exception
)
666 return safelyRetrieveValue
< sal_Int16
>(columnIndex
, SQL_SHORT
);
669 sal_Int32 SAL_CALL
OResultSet::getInt(sal_Int32 columnIndex
)
670 throw(SQLException
, RuntimeException
, std::exception
)
672 return safelyRetrieveValue
< sal_Int32
>(columnIndex
, SQL_LONG
);
675 sal_Int64 SAL_CALL
OResultSet::getLong(sal_Int32 columnIndex
)
676 throw(SQLException
, RuntimeException
, std::exception
)
678 return safelyRetrieveValue
< sal_Int64
>(columnIndex
, SQL_INT64
);
681 float SAL_CALL
OResultSet::getFloat(sal_Int32 columnIndex
)
682 throw(SQLException
, RuntimeException
, std::exception
)
684 return safelyRetrieveValue
< float >(columnIndex
, SQL_FLOAT
);
687 double SAL_CALL
OResultSet::getDouble(sal_Int32 columnIndex
)
688 throw(SQLException
, RuntimeException
, std::exception
)
690 return safelyRetrieveValue
< double >(columnIndex
, SQL_DOUBLE
);
693 // ---- XRow: More complex types ----------------------------------------------
694 OUString SAL_CALL
OResultSet::getString(sal_Int32 nIndex
)
695 throw(SQLException
, RuntimeException
, std::exception
)
697 return safelyRetrieveValue
< OUString
>(nIndex
);
700 Date SAL_CALL
OResultSet::getDate(sal_Int32 nIndex
)
701 throw(SQLException
, RuntimeException
, std::exception
)
703 return safelyRetrieveValue
< Date
>(nIndex
, SQL_TYPE_DATE
);
706 Time SAL_CALL
OResultSet::getTime(sal_Int32 nIndex
)
707 throw(SQLException
, RuntimeException
, std::exception
)
709 return safelyRetrieveValue
< css::util::Time
>(nIndex
, SQL_TYPE_TIME
);
712 DateTime SAL_CALL
OResultSet::getTimestamp(sal_Int32 nIndex
)
713 throw(SQLException
, RuntimeException
, std::exception
)
715 return safelyRetrieveValue
< DateTime
>(nIndex
, SQL_TIMESTAMP
);
719 uno::Reference
< XResultSetMetaData
> SAL_CALL
OResultSet::getMetaData( ) throw(SQLException
, RuntimeException
, std::exception
)
721 MutexGuard
aGuard(m_rMutex
);
722 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
724 if(!m_xMetaData
.is())
725 m_xMetaData
= new OResultSetMetaData(m_pConnection
730 uno::Reference
< XArray
> SAL_CALL
OResultSet::getArray( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
733 MutexGuard
aGuard(m_rMutex
);
734 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
740 uno::Reference
< XClob
> SAL_CALL
OResultSet::getClob( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
743 MutexGuard
aGuard(m_rMutex
);
744 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
746 int aSqlSubType
= m_pSqlda
->sqlvar
[columnIndex
-1].sqlsubtype
;
748 SAL_WARN_IF(aSqlSubType
!= 1,
749 "connectivity.firebird", "wrong subtype, not a textual blob");
751 ISC_QUAD
* pBlobID
= safelyRetrieveValue
< ISC_QUAD
* >(columnIndex
, SQL_BLOB
);
754 return m_pConnection
->createClob(pBlobID
);
757 uno::Reference
< XBlob
> SAL_CALL
OResultSet::getBlob(sal_Int32 columnIndex
)
758 throw(SQLException
, RuntimeException
, std::exception
)
760 MutexGuard
aGuard(m_rMutex
);
761 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
763 // TODO: CLOB etc. should be valid here too, but we probably want some more
764 // cleverness around this.
765 ISC_QUAD
* pBlobID
= safelyRetrieveValue
< ISC_QUAD
* >(columnIndex
, SQL_BLOB
);
768 return m_pConnection
->createBlob(pBlobID
);
772 uno::Reference
< XRef
> SAL_CALL
OResultSet::getRef( sal_Int32 columnIndex
) throw(SQLException
, RuntimeException
, std::exception
)
775 MutexGuard
aGuard(m_rMutex
);
776 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
782 Any SAL_CALL
OResultSet::getObject( sal_Int32 columnIndex
, const uno::Reference
< css::container::XNameAccess
>& typeMap
) throw(SQLException
, RuntimeException
, std::exception
)
786 MutexGuard
aGuard(m_rMutex
);
787 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
793 void SAL_CALL
OResultSet::close() throw(SQLException
, RuntimeException
, std::exception
)
795 SAL_INFO("connectivity.firebird", "close().");
798 MutexGuard
aGuard(m_rMutex
);
799 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
805 uno::Reference
< XInterface
> SAL_CALL
OResultSet::getStatement()
806 throw(SQLException
, RuntimeException
, std::exception
)
808 MutexGuard
aGuard(m_rMutex
);
809 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
813 //----- XResultSet: unsupported change detection methods ---------------------
814 sal_Bool SAL_CALL
OResultSet::rowDeleted() throw(SQLException
, RuntimeException
, std::exception
)
816 ::dbtools::throwFunctionNotSupportedSQLException("rowDeleted not supported in firebird",
820 sal_Bool SAL_CALL
OResultSet::rowInserted() throw(SQLException
, RuntimeException
, std::exception
)
822 ::dbtools::throwFunctionNotSupportedSQLException("rowInserted not supported in firebird",
827 sal_Bool SAL_CALL
OResultSet::rowUpdated() throw(SQLException
, RuntimeException
, std::exception
)
829 ::dbtools::throwFunctionNotSupportedSQLException("rowUpdated not supported in firebird",
834 void SAL_CALL
OResultSet::refreshRow() throw(SQLException
, RuntimeException
, std::exception
)
836 ::dbtools::throwFunctionNotSupportedSQLException("refreshRow not supported in firebird",
841 void SAL_CALL
OResultSet::cancel( ) throw(RuntimeException
, std::exception
)
843 MutexGuard
aGuard(m_rMutex
);
844 checkDisposed(OResultSet_BASE::rBHelper
.bDisposed
);
848 //----- XWarningsSupplier UNSUPPORTED -----------------------------------------
850 void SAL_CALL
OResultSet::clearWarnings() throw(SQLException
, RuntimeException
, std::exception
)
852 ::dbtools::throwFunctionNotSupportedSQLException("clearWarnings not supported in firebird",
856 Any SAL_CALL
OResultSet::getWarnings() throw(SQLException
, RuntimeException
, std::exception
)
858 ::dbtools::throwFunctionNotSupportedSQLException("getWarnings not supported in firebird",
864 //----- OIdPropertyArrayUsageHelper ------------------------------------------
865 IPropertyArrayHelper
* OResultSet::createArrayHelper() const
867 Sequence
< Property
> aProperties
;
868 describeProperties(aProperties
);
869 return new ::cppu::OPropertyArrayHelper(aProperties
);
872 IPropertyArrayHelper
& OResultSet::getInfoHelper()
874 return *getArrayHelper();
877 void SAL_CALL
OResultSet::acquire() throw()
879 OResultSet_BASE::acquire();
882 void SAL_CALL
OResultSet::release() throw()
884 OResultSet_BASE::release();
887 uno::Reference
< css::beans::XPropertySetInfo
> SAL_CALL
OResultSet::getPropertySetInfo( ) throw(css::uno::RuntimeException
, std::exception
)
889 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
892 // ---- XServiceInfo -----------------------------------------------------------
893 OUString SAL_CALL
OResultSet::getImplementationName() throw ( RuntimeException
, std::exception
)
895 return OUString("com.sun.star.sdbcx.firebird.ResultSet");
898 Sequence
< OUString
> SAL_CALL
OResultSet::getSupportedServiceNames()
899 throw( RuntimeException
, std::exception
)
901 return {"com.sun.star.sdbc.ResultSet","com.sun.star.sdbcx.ResultSet"};
904 sal_Bool SAL_CALL
OResultSet::supportsService(const OUString
& _rServiceName
)
905 throw( RuntimeException
, std::exception
)
907 return cppu::supportsService(this, _rServiceName
);
910 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */