LCOV - code coverage report
Current view: top level - connectivity/source/drivers/firebird - ResultSet.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 123 312 39.4 %
Date: 2014-04-11 Functions: 31 82 37.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include "ResultSet.hxx"
      21             : #include "ResultSetMetaData.hxx"
      22             : #include "Util.hxx"
      23             : 
      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>
      33             : 
      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>
      38             : 
      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;
      45             : using namespace ::rtl;
      46             : 
      47             : using namespace ::com::sun::star;
      48             : using namespace ::com::sun::star::uno;
      49             : using namespace ::com::sun::star::lang;
      50             : using namespace ::com::sun::star::beans;
      51             : using namespace ::com::sun::star::sdbc;
      52             : using namespace ::com::sun::star::sdbcx;
      53             : using namespace ::com::sun::star::container;
      54             : using namespace ::com::sun::star::io;
      55             : using namespace ::com::sun::star::util;
      56             : 
      57           9 : OResultSet::OResultSet(Connection* pConnection,
      58             :                        ::osl::Mutex& rMutex,
      59             :                        const uno::Reference< XInterface >& xStatement,
      60             :                        isc_stmt_handle& aStatementHandle,
      61             :                        XSQLDA* pSqlda)
      62             :     : OResultSet_BASE(rMutex)
      63             :     , OPropertyContainer(OResultSet_BASE::rBHelper)
      64             :     , m_bIsBookmarkable(false)
      65             :     , m_nFetchSize(1)
      66             :     , m_nResultSetType(::com::sun::star::sdbc::ResultSetType::FORWARD_ONLY)
      67             :     , m_nFetchDirection(::com::sun::star::sdbc::FetchDirection::FORWARD)
      68             :     , m_nResultSetConcurrency(::com::sun::star::sdbc::ResultSetConcurrency::READ_ONLY)
      69             :     , m_pConnection(pConnection)
      70             :     , m_rMutex(rMutex)
      71             :     , m_xStatement(xStatement)
      72             :     , m_xMetaData(0)
      73             :     , m_pSqlda(pSqlda)
      74             :     , m_statementHandle(aStatementHandle)
      75             :     , m_bWasNull(false)
      76             :     , m_currentRow(0)
      77             :     , m_bIsAfterLastRow(false)
      78           9 :     , m_fieldCount(pSqlda? pSqlda->sqld : 0)
      79             : {
      80             :     SAL_INFO("connectivity.firebird", "OResultSet().");
      81           9 :     registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ISBOOKMARKABLE),
      82             :                      PROPERTY_ID_ISBOOKMARKABLE,
      83             :                      PropertyAttribute::READONLY,
      84             :                      &m_bIsBookmarkable,
      85          18 :                      ::getCppuType(&m_bIsBookmarkable));
      86           9 :     registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE),
      87             :                      PROPERTY_ID_FETCHSIZE,
      88             :                      PropertyAttribute::READONLY,
      89             :                      &m_nFetchSize,
      90          18 :                      ::getCppuType(&m_nFetchSize));
      91           9 :     registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE),
      92             :                      PROPERTY_ID_RESULTSETTYPE,
      93             :                      PropertyAttribute::READONLY,
      94             :                      &m_nResultSetType,
      95          18 :                      ::getCppuType(&m_nResultSetType));
      96           9 :     registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION),
      97             :                      PROPERTY_ID_FETCHDIRECTION,
      98             :                      PropertyAttribute::READONLY,
      99             :                      &m_nFetchDirection,
     100          18 :                      ::getCppuType(&m_nFetchDirection));
     101           9 :     registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY),
     102             :                      PROPERTY_ID_RESULTSETCONCURRENCY,
     103             :                      PropertyAttribute::READONLY,
     104             :                      &m_nResultSetConcurrency,
     105          18 :                      ::getCppuType(&m_nResultSetConcurrency));
     106             : 
     107           9 :     if (!pSqlda)
     108           0 :         return; // TODO: what?
     109             : 
     110             : }
     111             : 
     112          18 : OResultSet::~OResultSet()
     113             : {
     114          18 : }
     115             : 
     116             : // ---- XResultSet -- Row retrieval methods ------------------------------------
     117           1 : sal_Int32 SAL_CALL OResultSet::getRow() throw(SQLException, RuntimeException, std::exception)
     118             : {
     119           1 :     MutexGuard aGuard(m_rMutex);
     120           1 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     121             : 
     122           1 :     return m_currentRow;
     123             : }
     124             : 
     125          18 : sal_Bool SAL_CALL OResultSet::next() throw(SQLException, RuntimeException, std::exception)
     126             : {
     127          18 :     MutexGuard aGuard(m_rMutex);
     128          18 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     129             : 
     130          18 :     m_currentRow++;
     131             : 
     132             :     ISC_STATUS fetchStat = isc_dsql_fetch(m_statusVector,
     133             :                                &m_statementHandle,
     134             :                                1,
     135          18 :                                m_pSqlda);
     136          18 :     if (fetchStat == 0)         // SUCCESSFUL
     137             :     {
     138          10 :         return sal_True;
     139             :     }
     140           8 :     else if (fetchStat == 100L) // END OF DATASET
     141             :     {
     142           8 :         m_bIsAfterLastRow = true;
     143           8 :         return sal_False;
     144             :     }
     145             :     else
     146             :     {
     147             :         SAL_WARN("connectivity.firebird", "Error when fetching data");
     148             :         // Throws sql exception as appropriate
     149           0 :         evaluateStatusVector(m_statusVector, "isc_dsql_fetch", *this);
     150           0 :         return sal_False;
     151          18 :     }
     152             : }
     153             : 
     154           0 : sal_Bool SAL_CALL OResultSet::previous() throw(SQLException, RuntimeException, std::exception)
     155             : {
     156             :     ::dbtools::throwFunctionNotSupportedException("previous not supported in firebird",
     157           0 :                                                   *this);
     158           0 :     return sal_False;
     159             : }
     160             : 
     161           0 : sal_Bool SAL_CALL OResultSet::isLast() throw(SQLException, RuntimeException, std::exception)
     162             : {
     163             :     ::dbtools::throwFunctionNotSupportedException("isLast not supported in firebird",
     164           0 :                                                   *this);
     165           0 :     return sal_False;
     166             : }
     167             : 
     168           0 : sal_Bool SAL_CALL OResultSet::isBeforeFirst() throw(SQLException, RuntimeException, std::exception)
     169             : {
     170           0 :     MutexGuard aGuard(m_rMutex);
     171           0 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     172             : 
     173           0 :     return m_currentRow == 0;
     174             : }
     175             : 
     176           0 : sal_Bool SAL_CALL OResultSet::isAfterLast() throw(SQLException, RuntimeException, std::exception)
     177             : {
     178           0 :     MutexGuard aGuard(m_rMutex);
     179           0 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     180             : 
     181           0 :     return m_bIsAfterLastRow;
     182             : }
     183             : 
     184           0 : sal_Bool SAL_CALL OResultSet::isFirst() throw(SQLException, RuntimeException, std::exception)
     185             : {
     186           0 :     MutexGuard aGuard(m_rMutex);
     187           0 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     188             : 
     189           0 :     return m_currentRow == 1 && !m_bIsAfterLastRow;
     190             : }
     191             : 
     192           0 : void SAL_CALL OResultSet::beforeFirst() throw(SQLException, RuntimeException, std::exception)
     193             : {
     194           0 :     MutexGuard aGuard(m_rMutex);
     195           0 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     196             : 
     197           0 :     if (m_currentRow != 0)
     198             :         ::dbtools::throwFunctionNotSupportedException("beforeFirst not supported in firebird",
     199           0 :                                                       *this);
     200           0 : }
     201             : 
     202           0 : void SAL_CALL OResultSet::afterLast() throw(SQLException, RuntimeException, std::exception)
     203             : {
     204           0 :     MutexGuard aGuard(m_rMutex);
     205           0 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     206             : 
     207           0 :     if (!m_bIsAfterLastRow)
     208             :         ::dbtools::throwFunctionNotSupportedException("afterLast not supported in firebird",
     209           0 :                                                       *this);
     210           0 : }
     211             : 
     212           0 : sal_Bool SAL_CALL OResultSet::first() throw(SQLException, RuntimeException, std::exception)
     213             : {
     214           0 :     MutexGuard aGuard(m_rMutex);
     215           0 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     216             : 
     217           0 :     if (m_currentRow == 0)
     218             :     {
     219           0 :         return next();
     220             :     }
     221           0 :     else if (m_currentRow == 1 && !m_bIsAfterLastRow)
     222             :     {
     223           0 :         return sal_True;
     224             :     }
     225             :     else
     226             :     {
     227             :         ::dbtools::throwFunctionNotSupportedException("first not supported in firebird",
     228           0 :                                                       *this);
     229           0 :         return sal_False;
     230           0 :     }
     231             : }
     232             : 
     233           0 : sal_Bool SAL_CALL OResultSet::last() throw(SQLException, RuntimeException, std::exception)
     234             : {
     235             :     // We need to iterate past the last row to know when we've passed the last
     236             :     // row, hence we can't actually move to last.
     237             :     ::dbtools::throwFunctionNotSupportedException("last not supported in firebird",
     238           0 :                                                   *this);
     239           0 :     return sal_False;
     240             : }
     241             : 
     242           0 : sal_Bool SAL_CALL OResultSet::absolute(sal_Int32 aRow) throw(SQLException, RuntimeException, std::exception)
     243             : {
     244           0 :     MutexGuard aGuard(m_rMutex);
     245           0 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     246             : 
     247           0 :     if (aRow > m_currentRow)
     248             :     {
     249           0 :         sal_Int32 aIterations = aRow - m_currentRow;
     250           0 :         return relative(aIterations);
     251             :     }
     252             :     else
     253             :     {
     254             :         ::dbtools::throwFunctionNotSupportedException("absolute not supported in firebird",
     255           0 :                                                       *this);
     256           0 :         return sal_False;
     257           0 :     }
     258             : }
     259             : 
     260           0 : sal_Bool SAL_CALL OResultSet::relative(sal_Int32 row) throw(SQLException, RuntimeException, std::exception)
     261             : {
     262           0 :     MutexGuard aGuard(m_rMutex);
     263           0 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     264             : 
     265           0 :     if (row > 0)
     266             :     {
     267           0 :         while (row--)
     268             :         {
     269           0 :             if (!next())
     270           0 :                 return sal_False;
     271             :         }
     272           0 :         return sal_True;
     273             :     }
     274             :     else
     275             :     {
     276             :         ::dbtools::throwFunctionNotSupportedException("relative not supported in firebird",
     277           0 :                                                       *this);
     278           0 :         return sal_False;
     279           0 :     }
     280             : }
     281             : 
     282          74 : void SAL_CALL OResultSet::checkColumnIndex(sal_Int32 nIndex)
     283             :     throw (SQLException, RuntimeException)
     284             : {
     285          74 :     MutexGuard aGuard(m_rMutex);
     286          74 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     287             : 
     288          74 :     if( nIndex < 1 || nIndex > m_fieldCount )
     289             :     {
     290             :         ::dbtools::throwSQLException(
     291           0 :             "No column " + OUString::number(nIndex),
     292             :             ::dbtools::SQL_COLUMN_NOT_FOUND,
     293           0 :             *this);
     294          74 :     }
     295          74 : }
     296             : 
     297          74 : void SAL_CALL OResultSet::checkRowIndex()
     298             :     throw (SQLException, RuntimeException)
     299             : {
     300          74 :     MutexGuard aGuard(m_rMutex);
     301          74 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     302             : 
     303          74 :     if((m_currentRow < 1) || m_bIsAfterLastRow)
     304             :     {
     305             :         ::dbtools::throwSQLException(
     306             :             "Invalid Row",
     307             :             ::dbtools::SQL_INVALID_CURSOR_POSITION,
     308           0 :             *this);
     309          74 :     }
     310          74 : }
     311             : 
     312          29 : Any SAL_CALL OResultSet::queryInterface( const Type & rType ) throw(RuntimeException, std::exception)
     313             : {
     314          29 :     Any aRet = OPropertySetHelper::queryInterface(rType);
     315          29 :     return aRet.hasValue() ? aRet : OResultSet_BASE::queryInterface(rType);
     316             : }
     317             : 
     318           0 :  Sequence<  Type > SAL_CALL OResultSet::getTypes() throw( RuntimeException, std::exception)
     319             : {
     320           0 :     return concatSequences(OPropertySetHelper::getTypes(), OResultSet_BASE::getTypes());
     321             : }
     322             : // ---- XColumnLocate ---------------------------------------------------------
     323           5 : sal_Int32 SAL_CALL OResultSet::findColumn(const OUString& rColumnName)
     324             :     throw(SQLException, RuntimeException, std::exception)
     325             : {
     326           5 :     MutexGuard aGuard(m_rMutex);
     327           5 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     328             : 
     329          10 :     uno::Reference< XResultSetMetaData > xMeta = getMetaData();
     330           5 :     sal_Int32 nLen = xMeta->getColumnCount();
     331             :     sal_Int32 i;
     332             : 
     333          20 :     for(i = 1; i<=nLen; ++i)
     334             :     {
     335             :         // We assume case sensitive, otherwise you'd have to test
     336             :         // xMeta->isCaseSensitive and use qualsIgnoreAsciiCase as needed.
     337          20 :         if (rColumnName == xMeta->getColumnName(i))
     338           5 :             return i;
     339             :     }
     340             : 
     341           0 :     ::dbtools::throwInvalidColumnException(rColumnName, *this);
     342             :     assert(false);
     343           5 :     return 0; // Never reached
     344             : }
     345             : 
     346           0 : uno::Reference< XInputStream > SAL_CALL OResultSet::getBinaryStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
     347             : {
     348             :     (void) columnIndex;
     349           0 :     MutexGuard aGuard(m_rMutex);
     350           0 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     351             : 
     352           0 :     return NULL;
     353             : }
     354             : 
     355           0 : uno::Reference< XInputStream > SAL_CALL OResultSet::getCharacterStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
     356             : {
     357             :     (void) columnIndex;
     358           0 :     MutexGuard aGuard(m_rMutex);
     359           0 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     360             : 
     361           0 :     return NULL;
     362             : }
     363             : 
     364             : // ---- Internal Utilities ---------------------------------------------------
     365         103 : bool OResultSet::isNull(const sal_Int32 nColumnIndex)
     366             : {
     367             :     assert(nColumnIndex <= m_fieldCount);
     368         103 :     XSQLVAR* pVar = m_pSqlda->sqlvar;
     369             : 
     370         103 :     if (pVar[nColumnIndex-1].sqltype & 1) // Indicates column may contain null
     371             :     {
     372         103 :         if (*pVar[nColumnIndex-1].sqlind == -1)
     373          26 :             return true;
     374             :     }
     375          77 :     return false;
     376             : }
     377             : 
     378             : template <typename T>
     379          29 : T OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT nType)
     380             : {
     381          29 :     if ((m_bWasNull = isNull(nColumnIndex)))
     382           0 :         return T();
     383             : 
     384          29 :     if ((m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1) == nType)
     385          29 :         return *((T*) m_pSqlda->sqlvar[nColumnIndex-1].sqldata);
     386             :     else
     387           0 :         return retrieveValue< ORowSetValue >(nColumnIndex, 0);
     388             : }
     389             : 
     390             : template <>
     391           0 : ORowSetValue OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT /*nType*/)
     392             : {
     393             :     // See http://wiki.openoffice.org/wiki/Documentation/DevGuide/Database/Using_the_getXXX_Methods
     394             :     // (bottom of page) for a chart of possible conversions, we should allow all
     395             :     // of these -- Blob/Clob will probably need some specialist handling especially
     396             :     // w.r.t. to generating Strings for them.
     397             :     //
     398             :     // Basically we just have to map to the correct direct request and
     399             :     // ORowSetValue does the rest for us here.
     400           0 :     switch (m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1)
     401             :     {
     402             :         case SQL_TEXT:
     403             :         case SQL_VARYING:
     404           0 :             return getString(nColumnIndex);
     405             :         case SQL_SHORT:
     406           0 :             return getShort(nColumnIndex);
     407             :         case SQL_LONG:
     408           0 :             return getInt(nColumnIndex);
     409             :         case SQL_FLOAT:
     410           0 :             return getFloat(nColumnIndex);
     411             :         case SQL_DOUBLE:
     412           0 :             return getDouble(nColumnIndex);
     413             :         case SQL_D_FLOAT:
     414           0 :             return getFloat(nColumnIndex);
     415             :         case SQL_TIMESTAMP:
     416           0 :             return getTimestamp(nColumnIndex);
     417             :         case SQL_TYPE_TIME:
     418           0 :             return getTime(nColumnIndex);
     419             :         case SQL_TYPE_DATE:
     420           0 :             return getDate(nColumnIndex);
     421             :         case SQL_INT64:
     422           0 :             return getLong(nColumnIndex);
     423             :         case SQL_BLOB:
     424             :         case SQL_NULL:
     425             :         case SQL_QUAD:
     426             :         case SQL_ARRAY:
     427             :             // TODO: these are all invalid conversions, so maybe we should
     428             :             // throw an exception?
     429           0 :             return ORowSetValue();
     430             :         default:
     431             :             assert(false);
     432           0 :             return ORowSetValue();
     433             :     }
     434             : }
     435             : 
     436             : template <>
     437           0 : Date OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT /*nType*/)
     438             : {
     439           0 :     if ((m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1) == SQL_TYPE_DATE)
     440             :     {
     441           0 :         ISC_DATE aISCDate = *((ISC_DATE*) m_pSqlda->sqlvar[nColumnIndex-1].sqldata);
     442             : 
     443             :         struct tm aCTime;
     444           0 :         isc_decode_sql_date(&aISCDate, &aCTime);
     445             : 
     446           0 :         return Date(aCTime.tm_mday, aCTime.tm_mon, aCTime.tm_year);
     447             :     }
     448             :     else
     449             :     {
     450           0 :         return retrieveValue< ORowSetValue >(nColumnIndex, 0);
     451             :     }
     452             : }
     453             : 
     454             : template <>
     455           0 : Time OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT /*nType*/)
     456             : {
     457           0 :     if ((m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1) == SQL_TYPE_TIME)
     458             :     {
     459           0 :         ISC_TIME aISCTime = *((ISC_TIME*) m_pSqlda->sqlvar[nColumnIndex-1].sqldata);
     460             : 
     461             :         struct tm aCTime;
     462           0 :         isc_decode_sql_time(&aISCTime, &aCTime);
     463             : 
     464             :         // first field is nanoseconds -- not supported in firebird or struct tm.
     465             :         // last field denotes UTC (true) or unknown (false)
     466           0 :         return Time(0, aCTime.tm_sec, aCTime.tm_min, aCTime.tm_hour, false);
     467             :     }
     468             :     else
     469             :     {
     470           0 :         return retrieveValue< ORowSetValue >(nColumnIndex, 0);
     471             :     }
     472             : }
     473             : 
     474             : template <>
     475           0 : DateTime OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT /*nType*/)
     476             : {
     477           0 :     if ((m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1) == SQL_TIMESTAMP)
     478             :     {
     479           0 :         ISC_TIMESTAMP aISCTimestamp = *((ISC_TIMESTAMP*) m_pSqlda->sqlvar[nColumnIndex-1].sqldata);
     480             : 
     481             :         struct tm aCTime;
     482           0 :         isc_decode_timestamp(&aISCTimestamp, &aCTime);
     483             : 
     484             :         // first field is nanoseconds -- not supported in firebird or struct tm.
     485             :         // last field denotes UTC (true) or unknown (false)
     486             :         return DateTime(0, aCTime.tm_sec, aCTime.tm_min, aCTime.tm_hour, aCTime.tm_mday,
     487           0 :                     aCTime.tm_mon, aCTime.tm_year, false);
     488             :     }
     489             :     else
     490             :     {
     491           0 :         return retrieveValue< ORowSetValue >(nColumnIndex, 0);
     492             :     }
     493             : }
     494             : 
     495             : template <>
     496          19 : OUString OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT /*nType*/)
     497             : {
     498             :     // &~1 to remove the "can contain NULL" indicator
     499          19 :     int aSqlType = m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1;
     500          19 :     if (aSqlType == SQL_TEXT )
     501             :     {
     502          18 :         return OUString(m_pSqlda->sqlvar[nColumnIndex-1].sqldata,
     503          18 :                         m_pSqlda->sqlvar[nColumnIndex-1].sqllen,
     504          54 :                         RTL_TEXTENCODING_UTF8);
     505             :     }
     506           1 :     else if (aSqlType == SQL_VARYING)
     507             :     {
     508             :         // First 2 bytes are a short containing the length of the string
     509             :         // No idea if sqllen is still valid here?
     510           1 :         sal_uInt16 aLength = *((sal_uInt16*) m_pSqlda->sqlvar[nColumnIndex-1].sqldata);
     511           1 :         return OUString(m_pSqlda->sqlvar[nColumnIndex-1].sqldata + 2,
     512             :                         aLength,
     513           2 :                         RTL_TEXTENCODING_UTF8);
     514             :     }
     515             :     else
     516             :     {
     517           0 :         return retrieveValue< ORowSetValue >(nColumnIndex, 0);
     518             :     }
     519             : }
     520             : 
     521             : template <>
     522           0 : ISC_QUAD* OResultSet::retrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT nType)
     523             : {
     524             :     // TODO: this is probably wrong
     525           0 :     if ((m_pSqlda->sqlvar[nColumnIndex-1].sqltype & ~1) == nType)
     526           0 :         return (ISC_QUAD*) m_pSqlda->sqlvar[nColumnIndex-1].sqldata;
     527             :     else
     528           0 :         throw SQLException(); // TODO: better exception (can't convert Blob)
     529             : }
     530             : 
     531             : template <typename T>
     532          74 : T OResultSet::safelyRetrieveValue(const sal_Int32 nColumnIndex, const ISC_SHORT nType)
     533             : {
     534          74 :     MutexGuard aGuard(m_rMutex);
     535          74 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     536             : 
     537          74 :     checkColumnIndex(nColumnIndex);
     538          74 :     checkRowIndex();
     539             : 
     540          74 :     if ((m_bWasNull = isNull(nColumnIndex)))
     541          26 :         return T();
     542             : 
     543          48 :     return retrieveValue< T >(nColumnIndex, nType);
     544             : }
     545             : 
     546             : // ---- XRow -----------------------------------------------------------------
     547           2 : sal_Bool SAL_CALL OResultSet::wasNull() throw(SQLException, RuntimeException, std::exception)
     548             : {
     549           2 :     MutexGuard aGuard(m_rMutex);
     550           2 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     551             : 
     552           2 :     return m_bWasNull;
     553             : }
     554             : 
     555             : // ---- XRow: Simple Numerical types ------------------------------------------
     556           0 : sal_Bool SAL_CALL OResultSet::getBoolean(sal_Int32 nColumnIndex)
     557             :     throw(SQLException, RuntimeException, std::exception)
     558             : {
     559             :     // Not a native firebird type hence we always have to convert.
     560           0 :     return safelyRetrieveValue< ORowSetValue >(nColumnIndex);
     561             : }
     562             : 
     563           0 : sal_Int8 SAL_CALL OResultSet::getByte(sal_Int32 nColumnIndex)
     564             :     throw(SQLException, RuntimeException, std::exception)
     565             : {
     566             :     // Not a native firebird type hence we always have to convert.
     567           0 :     return safelyRetrieveValue< ORowSetValue >(nColumnIndex);
     568             : }
     569             : 
     570           0 : Sequence< sal_Int8 > SAL_CALL OResultSet::getBytes(sal_Int32 columnIndex)
     571             :     throw(SQLException, RuntimeException, std::exception)
     572             : {
     573             :     (void) columnIndex;
     574           0 :     return Sequence< sal_Int8 >(); // TODO: implement
     575             :     //return safelyRetrieveValue(columnIndex);
     576             : }
     577             : 
     578          37 : sal_Int16 SAL_CALL OResultSet::getShort(sal_Int32 columnIndex)
     579             :     throw(SQLException, RuntimeException, std::exception)
     580             : {
     581          37 :     return safelyRetrieveValue< sal_Int16 >(columnIndex, SQL_SHORT);
     582             : }
     583             : 
     584           1 : sal_Int32 SAL_CALL OResultSet::getInt(sal_Int32 columnIndex)
     585             :     throw(SQLException, RuntimeException, std::exception)
     586             : {
     587           1 :     return safelyRetrieveValue< sal_Int32 >(columnIndex, SQL_LONG);
     588             : }
     589             : 
     590           1 : sal_Int64 SAL_CALL OResultSet::getLong(sal_Int32 columnIndex)
     591             :     throw(SQLException, RuntimeException, std::exception)
     592             : {
     593           1 :     return safelyRetrieveValue< sal_Int64 >(columnIndex, SQL_INT64);
     594             : }
     595             : 
     596           0 : float SAL_CALL OResultSet::getFloat(sal_Int32 columnIndex)
     597             :     throw(SQLException, RuntimeException, std::exception)
     598             : {
     599           0 :     return safelyRetrieveValue< float >(columnIndex, SQL_FLOAT);
     600             : }
     601             : 
     602           0 : double SAL_CALL OResultSet::getDouble(sal_Int32 columnIndex)
     603             :     throw(SQLException, RuntimeException, std::exception)
     604             : {
     605           0 :     return safelyRetrieveValue< double >(columnIndex, SQL_DOUBLE);
     606             : }
     607             : 
     608             : // ---- XRow: More complex types ----------------------------------------------
     609          19 : OUString SAL_CALL OResultSet::getString(sal_Int32 nIndex)
     610             :     throw(SQLException, RuntimeException, std::exception)
     611             : {
     612          19 :     return safelyRetrieveValue< OUString >(nIndex);
     613             : }
     614             : 
     615           0 : Date SAL_CALL OResultSet::getDate(sal_Int32 nIndex)
     616             :     throw(SQLException, RuntimeException, std::exception)
     617             : {
     618           0 :     return safelyRetrieveValue< Date >(nIndex, SQL_TYPE_DATE);
     619             : }
     620             : 
     621           0 : Time SAL_CALL OResultSet::getTime(sal_Int32 nIndex)
     622             :     throw(SQLException, RuntimeException, std::exception)
     623             : {
     624           0 :     return safelyRetrieveValue< Time >(nIndex, SQL_TYPE_TIME);
     625             : }
     626             : 
     627           0 : DateTime SAL_CALL OResultSet::getTimestamp(sal_Int32 nIndex)
     628             :     throw(SQLException, RuntimeException, std::exception)
     629             : {
     630           0 :     return safelyRetrieveValue< DateTime >(nIndex, SQL_TIMESTAMP);
     631             : }
     632             : 
     633             : 
     634           6 : uno::Reference< XResultSetMetaData > SAL_CALL OResultSet::getMetaData(  ) throw(SQLException, RuntimeException, std::exception)
     635             : {
     636           6 :     MutexGuard aGuard(m_rMutex);
     637           6 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     638             : 
     639           6 :     if(!m_xMetaData.is())
     640           2 :         m_xMetaData = new OResultSetMetaData(m_pConnection, m_pSqlda);
     641           6 :     return m_xMetaData;
     642             : }
     643             : 
     644           0 : uno::Reference< XArray > SAL_CALL OResultSet::getArray( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
     645             : {
     646             :     (void) columnIndex;
     647           0 :     MutexGuard aGuard(m_rMutex);
     648           0 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     649             : 
     650           0 :     return NULL;
     651             : }
     652             : 
     653             : 
     654             : 
     655           0 : uno::Reference< XClob > SAL_CALL OResultSet::getClob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
     656             : {
     657             :     (void) columnIndex;
     658           0 :     MutexGuard aGuard(m_rMutex);
     659           0 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     660             : 
     661           0 :     return NULL;
     662             : }
     663             : 
     664          16 : uno::Reference< XBlob > SAL_CALL OResultSet::getBlob(sal_Int32 columnIndex)
     665             :     throw(SQLException, RuntimeException, std::exception)
     666             : {
     667          16 :     MutexGuard aGuard(m_rMutex);
     668          16 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     669             : 
     670             :     // TODO: CLOB etc. should be valid here too, but we probably want some more
     671             :     // cleverness around this.
     672          16 :     ISC_QUAD* pBlobID = safelyRetrieveValue< ISC_QUAD* >(columnIndex, SQL_BLOB);
     673          16 :     if (!pBlobID)
     674          16 :         return 0;
     675           0 :     return m_pConnection->createBlob(pBlobID);
     676             : }
     677             : 
     678             : 
     679           0 : uno::Reference< XRef > SAL_CALL OResultSet::getRef( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
     680             : {
     681             :     (void) columnIndex;
     682           0 :     MutexGuard aGuard(m_rMutex);
     683           0 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     684             : 
     685           0 :     return NULL;
     686             : }
     687             : 
     688             : 
     689           0 : Any SAL_CALL OResultSet::getObject( sal_Int32 columnIndex, const uno::Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(SQLException, RuntimeException, std::exception)
     690             : {
     691             :     (void) columnIndex;
     692             :     (void) typeMap;
     693           0 :     MutexGuard aGuard(m_rMutex);
     694           0 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     695             : 
     696           0 :     return Any();
     697             : }
     698             : 
     699             : 
     700             : 
     701             : 
     702             : 
     703           1 : void SAL_CALL OResultSet::close() throw(SQLException, RuntimeException, std::exception)
     704             : {
     705             :     SAL_INFO("connectivity.firebird", "close().");
     706             : 
     707             :     {
     708           1 :         MutexGuard aGuard(m_rMutex);
     709           1 :         checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     710             :     }
     711           1 :     dispose();
     712           1 : }
     713             : 
     714             : 
     715           0 : uno::Reference< XInterface > SAL_CALL OResultSet::getStatement()
     716             :     throw(SQLException, RuntimeException, std::exception)
     717             : {
     718           0 :     MutexGuard aGuard(m_rMutex);
     719           0 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     720             : 
     721           0 :     return m_xStatement;
     722             : }
     723             : //----- XResultSet: unsupported change detection methods ---------------------
     724           0 : sal_Bool SAL_CALL OResultSet::rowDeleted() throw(SQLException, RuntimeException, std::exception)
     725             : {
     726             :     ::dbtools::throwFunctionNotSupportedException("rowDeleted not supported in firebird",
     727           0 :                                                   *this);
     728           0 :     return sal_False;
     729             : }
     730           0 : sal_Bool SAL_CALL OResultSet::rowInserted() throw(SQLException, RuntimeException, std::exception)
     731             : {
     732             :     ::dbtools::throwFunctionNotSupportedException("rowInserted not supported in firebird",
     733           0 :                                                   *this);
     734           0 :     return sal_False;
     735             : }
     736             : 
     737           0 : sal_Bool SAL_CALL OResultSet::rowUpdated() throw(SQLException, RuntimeException, std::exception)
     738             : {
     739             :     ::dbtools::throwFunctionNotSupportedException("rowUpdated not supported in firebird",
     740           0 :                                                   *this);
     741           0 :     return sal_False;
     742             : }
     743             : 
     744           0 : void SAL_CALL OResultSet::refreshRow() throw(SQLException, RuntimeException, std::exception)
     745             : {
     746             :     ::dbtools::throwFunctionNotSupportedException("refreshRow not supported in firebird",
     747           0 :                                                   *this);
     748           0 : }
     749             : 
     750             : 
     751           0 : void SAL_CALL OResultSet::cancel(  ) throw(RuntimeException, std::exception)
     752             : {
     753           0 :     MutexGuard aGuard(m_rMutex);
     754           0 :     checkDisposed(OResultSet_BASE::rBHelper.bDisposed);
     755             : 
     756           0 : }
     757             : 
     758             : //----- XWarningsSupplier UNSUPPORTED -----------------------------------------
     759           0 : void SAL_CALL OResultSet::clearWarnings() throw(SQLException, RuntimeException, std::exception)
     760             : {
     761             :     ::dbtools::throwFunctionNotSupportedException("clearWarnings not supported in firebird",
     762           0 :                                                   *this);
     763           0 : }
     764             : 
     765           0 : Any SAL_CALL OResultSet::getWarnings() throw(SQLException, RuntimeException, std::exception)
     766             : {
     767             :     ::dbtools::throwFunctionNotSupportedException("getWarnings not supported in firebird",
     768           0 :                                                   *this);
     769           0 :     return Any();
     770             : }
     771             : 
     772             : //----- OIdPropertyArrayUsageHelper ------------------------------------------
     773           1 : IPropertyArrayHelper* OResultSet::createArrayHelper() const
     774             : {
     775           1 :     Sequence< Property > aProperties;
     776           1 :     describeProperties(aProperties);
     777           1 :     return new ::cppu::OPropertyArrayHelper(aProperties);
     778             : }
     779             : 
     780           4 : IPropertyArrayHelper & OResultSet::getInfoHelper()
     781             : {
     782           4 :     return *const_cast<OResultSet*>(this)->getArrayHelper();
     783             : }
     784             : 
     785          67 : void SAL_CALL OResultSet::acquire() throw()
     786             : {
     787          67 :     OResultSet_BASE::acquire();
     788          67 : }
     789             : 
     790          67 : void SAL_CALL OResultSet::release() throw()
     791             : {
     792          67 :     OResultSet_BASE::release();
     793          67 : }
     794             : 
     795           0 : uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL OResultSet::getPropertySetInfo(  ) throw(::com::sun::star::uno::RuntimeException, std::exception)
     796             : {
     797           0 :     return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
     798             : }
     799             : 
     800             : // ---- XServiceInfo -----------------------------------------------------------
     801           0 : OUString SAL_CALL OResultSet::getImplementationName() throw ( RuntimeException, std::exception)
     802             : {
     803           0 :     return OUString("com.sun.star.sdbcx.firebird.ResultSet");
     804             : }
     805             : 
     806           0 : Sequence< OUString > SAL_CALL OResultSet::getSupportedServiceNames()
     807             :     throw( RuntimeException, std::exception)
     808             : {
     809           0 :      Sequence< OUString > aSupported(2);
     810           0 :     aSupported[0] = "com.sun.star.sdbc.ResultSet";
     811           0 :     aSupported[1] = "com.sun.star.sdbcx.ResultSet";
     812           0 :     return aSupported;
     813             : }
     814             : 
     815           0 : sal_Bool SAL_CALL OResultSet::supportsService(const OUString& _rServiceName)
     816             :     throw( RuntimeException, std::exception)
     817             : {
     818           0 :     return cppu::supportsService(this, _rServiceName);
     819             : }
     820             : 
     821             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10