build fix
[LibreOffice.git] / connectivity / source / drivers / firebird / ResultSet.cxx
blob1c604547703579556c4f87c6410fa55162d85c1d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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"
22 #include "Util.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>
31 #include <time.h>
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,
57 ::osl::Mutex& rMutex,
58 const uno::Reference< XInterface >& xStatement,
59 isc_stmt_handle& aStatementHandle,
60 XSQLDA* pSqlda )
61 : OResultSet_BASE(rMutex)
62 , OPropertyContainer(OResultSet_BASE::rBHelper)
63 , m_bIsBookmarkable(false)
64 , m_nFetchSize(1)
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)
69 , m_rMutex(rMutex)
70 , m_xStatement(xStatement)
71 , m_xMetaData(nullptr)
72 , m_pSqlda(pSqlda)
73 , m_statementHandle(aStatementHandle)
74 , m_bWasNull(false)
75 , m_currentRow(0)
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,
83 &m_bIsBookmarkable,
84 cppu::UnoType<decltype(m_bIsBookmarkable)>::get());
85 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE),
86 PROPERTY_ID_FETCHSIZE,
87 PropertyAttribute::READONLY,
88 &m_nFetchSize,
89 cppu::UnoType<decltype(m_nFetchSize)>::get());
90 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE),
91 PROPERTY_ID_RESULTSETTYPE,
92 PropertyAttribute::READONLY,
93 &m_nResultSetType,
94 cppu::UnoType<decltype(m_nResultSetType)>::get());
95 registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION),
96 PROPERTY_ID_FETCHDIRECTION,
97 PropertyAttribute::READONLY,
98 &m_nFetchDirection,
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());
106 if (!pSqlda)
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);
121 return m_currentRow;
124 sal_Bool SAL_CALL OResultSet::next() throw(SQLException, RuntimeException, std::exception)
126 MutexGuard aGuard(m_rMutex);
127 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
129 m_currentRow++;
131 ISC_STATUS fetchStat = isc_dsql_fetch(m_statusVector,
132 &m_statementHandle,
134 m_pSqlda);
135 if (fetchStat == 0) // SUCCESSFUL
137 return true;
139 else if (fetchStat == 100) // END OF DATASET
141 m_bIsAfterLastRow = true;
142 return false;
144 else
146 SAL_WARN("connectivity.firebird", "Error when fetching data");
147 // Throws sql exception as appropriate
148 evaluateStatusVector(m_statusVector, "isc_dsql_fetch", *this);
149 return false;
153 sal_Bool SAL_CALL OResultSet::previous() throw(SQLException, RuntimeException, std::exception)
155 ::dbtools::throwFunctionNotSupportedSQLException("previous not supported in firebird",
156 *this);
157 return false;
160 sal_Bool SAL_CALL OResultSet::isLast() throw(SQLException, RuntimeException, std::exception)
162 ::dbtools::throwFunctionNotSupportedSQLException("isLast not supported in firebird",
163 *this);
164 return false;
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",
198 *this);
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",
208 *this);
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)
218 return next();
220 else if (m_currentRow == 1 && !m_bIsAfterLastRow)
222 return true;
224 else
226 ::dbtools::throwFunctionNotSupportedSQLException("first not supported in firebird",
227 *this);
228 return false;
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",
237 *this);
238 return false;
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);
251 else
253 ::dbtools::throwFunctionNotSupportedSQLException("absolute not supported in firebird",
254 *this);
255 return false;
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);
264 if (row > 0)
266 while (row--)
268 if (!next())
269 return false;
271 return true;
273 else
275 ::dbtools::throwFunctionNotSupportedSQLException("relative not supported in firebird",
276 *this);
277 return false;
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,
292 *this);
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(
305 "Invalid Row",
306 ::dbtools::StandardSQLState::INVALID_CURSOR_POSITION,
307 *this);
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();
330 sal_Int32 i;
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))
337 return i;
340 ::dbtools::throwInvalidColumnException(rColumnName, *this);
341 assert(false);
342 return 0; // Never reached
345 uno::Reference< XInputStream > SAL_CALL OResultSet::getBinaryStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
347 (void) columnIndex;
348 MutexGuard aGuard(m_rMutex);
349 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
351 return nullptr;
354 uno::Reference< XInputStream > SAL_CALL OResultSet::getCharacterStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
356 (void) columnIndex;
357 MutexGuard aGuard(m_rMutex);
358 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
360 return nullptr;
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)
372 return true;
374 return false;
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
385 assert(false);
386 return OUString();
389 OUStringBuffer sRetBuffer;
390 T nAllDigits = *reinterpret_cast<T*>(m_pSqlda->sqlvar[nColumnIndex-1].sqldata);
391 sal_Int64 nDecimalCountExp = pow10Integer(nDecimalCount);
393 if(nAllDigits < 0)
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;
408 while(nFracTemp>0)
410 nFracTemp /= 10;
411 iCount++;
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');
422 // the rest
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)))
433 return T();
435 if ((m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1) == nType)
436 return *reinterpret_cast<T*>(m_pSqlda->sqlvar[nColumnIndex-1].sqldata);
437 else
438 return retrieveValue< ORowSetValue >(nColumnIndex, 0);
441 template <>
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)
454 case SQL_TEXT:
455 case SQL_VARYING:
456 return getString(nColumnIndex);
457 case SQL_SHORT:
458 if(nSqlSubType == 1 || nSqlSubType == 2) //numeric or decimal
459 return getString(nColumnIndex);
460 return getShort(nColumnIndex);
461 case SQL_LONG:
462 if(nSqlSubType == 1 || nSqlSubType == 2) //numeric or decimal
463 return getString(nColumnIndex);
464 return getInt(nColumnIndex);
465 case SQL_FLOAT:
466 return getFloat(nColumnIndex);
467 case SQL_DOUBLE:
468 if(nSqlSubType == 1 || nSqlSubType == 2) //numeric or decimal
469 return getString(nColumnIndex);
470 return getDouble(nColumnIndex);
471 case SQL_D_FLOAT:
472 return getFloat(nColumnIndex);
473 case SQL_TIMESTAMP:
474 return getTimestamp(nColumnIndex);
475 case SQL_TYPE_TIME:
476 return getTime(nColumnIndex);
477 case SQL_TYPE_DATE:
478 return getDate(nColumnIndex);
479 case SQL_INT64:
480 if(nSqlSubType == 1 || nSqlSubType == 2) //numeric or decimal
481 return getString(nColumnIndex);
482 return getLong(nColumnIndex);
483 case SQL_BLOB:
484 case SQL_NULL:
485 case SQL_QUAD:
486 case SQL_ARRAY:
487 // TODO: these are all invalid conversions, so maybe we should
488 // throw an exception?
489 return ORowSetValue();
490 default:
491 assert(false);
492 return ORowSetValue();
496 template <>
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));
503 struct tm aCTime;
504 isc_decode_sql_date(&aISCDate, &aCTime);
506 return Date(aCTime.tm_mday, aCTime.tm_mon + 1, aCTime.tm_year + 1900);
508 else
510 return retrieveValue< ORowSetValue >(nColumnIndex, 0);
514 template <>
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));
521 struct tm aCTime;
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);
528 else
530 return retrieveValue< ORowSetValue >(nColumnIndex, 0);
534 template <>
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));
541 struct tm aCTime;
542 isc_decode_timestamp(&aISCTimestamp, &aCTime);
544 return DateTime(0, //nanoseconds, not supported
545 aCTime.tm_sec,
546 aCTime.tm_min,
547 aCTime.tm_hour,
548 aCTime.tm_mday,
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)
553 else
555 return retrieveValue< ORowSetValue >(nColumnIndex, 0);
559 template <>
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,
577 aLength,
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
585 switch(aSqlType)
587 case SQL_SHORT:
588 return makeNumericString<sal_Int16>(nColumnIndex);
589 case SQL_LONG:
590 return makeNumericString<sal_Int32>(nColumnIndex);
591 case SQL_DOUBLE:
592 // TODO FIXME 64 bits?
593 case SQL_INT64:
594 return makeNumericString<sal_Int64>(nColumnIndex);
595 default:
596 assert(false);
597 return OUString(); // never reached
600 else
602 return retrieveValue< ORowSetValue >(nColumnIndex, 0);
606 template <>
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);
612 else
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);
623 checkRowIndex();
625 if ((m_bWasNull = isNull(nColumnIndex)))
626 return T();
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);
637 return m_bWasNull;
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)
658 (void) columnIndex;
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
726 , m_pSqlda);
727 return m_xMetaData;
730 uno::Reference< XArray > SAL_CALL OResultSet::getArray( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
732 (void) columnIndex;
733 MutexGuard aGuard(m_rMutex);
734 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
736 return nullptr;
740 uno::Reference< XClob > SAL_CALL OResultSet::getClob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
742 (void) columnIndex;
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);
752 if (!pBlobID)
753 return nullptr;
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);
766 if (!pBlobID)
767 return nullptr;
768 return m_pConnection->createBlob(pBlobID);
772 uno::Reference< XRef > SAL_CALL OResultSet::getRef( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
774 (void) columnIndex;
775 MutexGuard aGuard(m_rMutex);
776 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
778 return nullptr;
782 Any SAL_CALL OResultSet::getObject( sal_Int32 columnIndex, const uno::Reference< css::container::XNameAccess >& typeMap ) throw(SQLException, RuntimeException, std::exception)
784 (void) columnIndex;
785 (void) typeMap;
786 MutexGuard aGuard(m_rMutex);
787 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
789 return Any();
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);
801 dispose();
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);
811 return m_xStatement;
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",
817 *this);
818 return false;
820 sal_Bool SAL_CALL OResultSet::rowInserted() throw(SQLException, RuntimeException, std::exception)
822 ::dbtools::throwFunctionNotSupportedSQLException("rowInserted not supported in firebird",
823 *this);
824 return false;
827 sal_Bool SAL_CALL OResultSet::rowUpdated() throw(SQLException, RuntimeException, std::exception)
829 ::dbtools::throwFunctionNotSupportedSQLException("rowUpdated not supported in firebird",
830 *this);
831 return false;
834 void SAL_CALL OResultSet::refreshRow() throw(SQLException, RuntimeException, std::exception)
836 ::dbtools::throwFunctionNotSupportedSQLException("refreshRow not supported in firebird",
837 *this);
841 void SAL_CALL OResultSet::cancel( ) throw(RuntimeException, std::exception)
843 MutexGuard aGuard(m_rMutex);
844 checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
848 //----- XWarningsSupplier UNSUPPORTED -----------------------------------------
849 #if 0
850 void SAL_CALL OResultSet::clearWarnings() throw(SQLException, RuntimeException, std::exception)
852 ::dbtools::throwFunctionNotSupportedSQLException("clearWarnings not supported in firebird",
853 *this);
856 Any SAL_CALL OResultSet::getWarnings() throw(SQLException, RuntimeException, std::exception)
858 ::dbtools::throwFunctionNotSupportedSQLException("getWarnings not supported in firebird",
859 *this);
860 return Any();
862 #endif
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: */