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

Generated by: LCOV version 1.10