LCOV - code coverage report
Current view: top level - dbaccess/source/core/api - RowSetCache.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 451 855 52.7 %
Date: 2012-08-25 Functions: 49 58 84.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 364 1826 19.9 %

           Branch data     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                 :            : 
      21                 :            : #include "BookmarkSet.hxx"
      22                 :            : #include "CRowSetColumn.hxx"
      23                 :            : #include "CRowSetDataColumn.hxx"
      24                 :            : #include "KeySet.hxx"
      25                 :            : #include "OptimisticSet.hxx"
      26                 :            : #include "RowSetBase.hxx"
      27                 :            : #include "RowSetCache.hxx"
      28                 :            : #include "StaticSet.hxx"
      29                 :            : #include "WrappedResultSet.hxx"
      30                 :            : #include "core_resource.hrc"
      31                 :            : #include "core_resource.hxx"
      32                 :            : #include "dbastrings.hrc"
      33                 :            : 
      34                 :            : #include <com/sun/star/sdbc/ColumnValue.hpp>
      35                 :            : #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
      36                 :            : #include <com/sun/star/sdbcx/CompareBookmark.hpp>
      37                 :            : #include <com/sun/star/sdbcx/KeyType.hpp>
      38                 :            : #include <com/sun/star/sdbcx/Privilege.hpp>
      39                 :            : #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
      40                 :            : #include <com/sun/star/sdbcx/XKeysSupplier.hpp>
      41                 :            : #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
      42                 :            : 
      43                 :            : #include <comphelper/extract.hxx>
      44                 :            : #include <comphelper/property.hxx>
      45                 :            : #include <comphelper/seqstream.hxx>
      46                 :            : #include <comphelper/uno3.hxx>
      47                 :            : #include <connectivity/dbexception.hxx>
      48                 :            : #include <connectivity/dbtools.hxx>
      49                 :            : #include <connectivity/sqliterator.hxx>
      50                 :            : #include <connectivity/sqlnode.hxx>
      51                 :            : #include <connectivity/sqlparse.hxx>
      52                 :            : #include <tools/debug.hxx>
      53                 :            : #include <tools/diagnose_ex.h>
      54                 :            : #include <osl/diagnose.h>
      55                 :            : 
      56                 :            : #include <algorithm>
      57                 :            : 
      58                 :            : using namespace dbaccess;
      59                 :            : using namespace dbtools;
      60                 :            : using namespace connectivity;
      61                 :            : using namespace ::com::sun::star::uno;
      62                 :            : using namespace ::com::sun::star::beans;
      63                 :            : using namespace ::com::sun::star::sdbc;
      64                 :            : using namespace ::com::sun::star::sdb;
      65                 :            : using namespace ::com::sun::star::sdbcx;
      66                 :            : using namespace ::com::sun::star::container;
      67                 :            : using namespace ::com::sun::star::lang;
      68                 :            : using namespace ::cppu;
      69                 :            : using namespace ::osl;
      70                 :            : 
      71                 :            : #define CHECK_MATRIX_POS(M) OSL_ENSURE(((M) >= static_cast<ORowSetMatrix::difference_type>(0)) && ((M) < static_cast<sal_Int32>(m_pMatrix->size())),"Position is invalid!")
      72                 :            : 
      73                 :            : // This class calls m_pCacheSet->FOO_checked(..., sal_False)
      74                 :            : // (where FOO is absolute, last, previous)
      75                 :            : // when it does not immediately care about the values in the row's columns.
      76                 :            : // As a corollary, m_pCacheSet may be left in an inconsistent state,
      77                 :            : // and all ->fillFOO calls (and ->getFOO) may fail or give wrong results,
      78                 :            : // until m_pCacheSet is moved (or refreshed) again.
      79                 :            : // So always make sure m_pCacheSet is moved or refreshed before accessing column values.
      80                 :            : 
      81                 :            : DBG_NAME(ORowSetCache)
      82                 :            : 
      83                 :         40 : ORowSetCache::ORowSetCache(const Reference< XResultSet >& _xRs,
      84                 :            :                            const Reference< XSingleSelectQueryAnalyzer >& _xAnalyzer,
      85                 :            :                            const ::comphelper::ComponentContext& _rContext,
      86                 :            :                            const ::rtl::OUString& _rUpdateTableName,
      87                 :            :                            sal_Bool&    _bModified,
      88                 :            :                            sal_Bool&    _bNew,
      89                 :            :                            const ORowSetValueVector& _aParameterValueForCache,
      90                 :            :                            const ::rtl::OUString& i_sRowSetFilter,
      91                 :            :                            sal_Int32 i_nMaxRows)
      92                 :            :     :m_xSet(_xRs)
      93 [ +  - ][ +  - ]:         80 :     ,m_xMetaData(Reference< XResultSetMetaDataSupplier >(_xRs,UNO_QUERY)->getMetaData())
      94                 :            :     ,m_aContext( _rContext )
      95                 :            :     ,m_pCacheSet(NULL)
      96                 :            :     ,m_pMatrix(NULL)
      97                 :            :     ,m_pInsertMatrix(NULL)
      98                 :            :     ,m_nLastColumnIndex(0)
      99                 :            :     ,m_nFetchSize(0)
     100                 :            :     ,m_nRowCount(0)
     101                 :            :     ,m_nPrivileges( Privilege::SELECT )
     102                 :            :     ,m_nPosition(0)
     103                 :            :     ,m_nStartPos(0)
     104                 :            :     ,m_nEndPos(0)
     105                 :            :     ,m_bRowCountFinal(sal_False)
     106                 :            :     ,m_bBeforeFirst(sal_True)
     107                 :            :     ,m_bAfterLast( sal_False )
     108                 :            :     ,m_bUpdated(sal_False)
     109                 :            :     ,m_bModified(_bModified)
     110         [ +  - ]:        120 :     ,m_bNew(_bNew)
           [ +  -  +  - ]
         [ +  - ][ +  - ]
     111                 :            : {
     112                 :            :     DBG_CTOR(ORowSetCache,NULL);
     113                 :            : 
     114                 :            :     // first try if the result can be used to do inserts and updates
     115         [ +  - ]:         40 :     Reference< XPropertySet> xProp(_xRs,UNO_QUERY);
     116 [ +  - ][ +  - ]:         40 :     Reference< XPropertySetInfo > xPropInfo = xProp->getPropertySetInfo();
     117                 :         40 :     sal_Bool bBookmarkable = sal_False;
     118                 :            :     try
     119                 :            :     {
     120         [ +  - ]:         40 :         Reference< XResultSetUpdate> xUp(_xRs,UNO_QUERY_THROW);
     121 [ +  - ][ +  - ]:         80 :         bBookmarkable = xPropInfo->hasPropertyByName(PROPERTY_ISBOOKMARKABLE) &&
         [ +  - ][ +  - ]
                 [ #  # ]
     122 [ +  - ][ +  - ]:         40 :                                 any2bool(xProp->getPropertyValue(PROPERTY_ISBOOKMARKABLE)) && Reference< XRowLocate >(_xRs, UNO_QUERY).is();
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ #  #  
             #  #  #  # ]
     123         [ +  - ]:         40 :         if ( bBookmarkable )
     124                 :            :         {
     125 [ +  - ][ +  - ]:         40 :             xUp->moveToInsertRow();
     126 [ +  - ][ +  - ]:         40 :             xUp->cancelRowUpdates();
     127 [ +  - ][ +  - ]:         40 :             _xRs->beforeFirst();
     128                 :         40 :             m_nPrivileges = Privilege::SELECT|Privilege::DELETE|Privilege::INSERT|Privilege::UPDATE;
     129         [ +  - ]:         40 :             m_pCacheSet = new WrappedResultSet(i_nMaxRows);
     130 [ +  - ][ +  - ]:         40 :             m_xCacheSet = m_pCacheSet;
     131         [ +  - ]:         40 :             m_pCacheSet->construct(_xRs,i_sRowSetFilter);
     132                 :            :             return;
     133 [ -  + ][ #  # ]:         40 :         }
     134                 :            :     }
     135         [ #  # ]:          0 :     catch(const Exception& ex)
     136                 :            :     {
     137                 :            :         (void)ex;
     138                 :            :     }
     139                 :            :     try
     140                 :            :     {
     141 [ #  # ][ #  # ]:          0 :         if ( xPropInfo->hasPropertyByName(PROPERTY_RESULTSETTYPE) &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  #  
                   #  # ]
     142 [ #  # ][ #  # ]:          0 :                             ::comphelper::getINT32(xProp->getPropertyValue(PROPERTY_RESULTSETTYPE)) != ResultSetType::FORWARD_ONLY)
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  # ]
     143 [ #  # ][ #  # ]:          0 :             _xRs->beforeFirst();
     144                 :            :     }
     145         [ #  # ]:          0 :     catch(const SQLException& e)
     146                 :            :     {
     147                 :            :         (void)e;
     148                 :            :     }
     149                 :            : 
     150                 :            :     // check if all keys of the updateable table are fetched
     151                 :          0 :     sal_Bool bAllKeysFound = sal_False;
     152                 :          0 :     sal_Int32 nTablesCount = 0;
     153                 :            : 
     154 [ #  # ][ #  # ]:          0 :     sal_Bool bNeedKeySet = !bBookmarkable || (xPropInfo->hasPropertyByName(PROPERTY_RESULTSETCONCURRENCY) &&
         [ #  # ][ #  # ]
                 [ #  # ]
     155 [ #  # ][ #  # ]:          0 :                             ::comphelper::getINT32(xProp->getPropertyValue(PROPERTY_RESULTSETCONCURRENCY)) == ResultSetConcurrency::READ_ONLY);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
     156                 :            : 
     157                 :          0 :     Reference< XIndexAccess> xUpdateTableKeys;
     158                 :          0 :     ::rtl::OUString aUpdateTableName = _rUpdateTableName;
     159                 :          0 :     Reference< XConnection> xConnection;
     160                 :            :     // first we need a connection
     161 [ #  # ][ #  # ]:          0 :     Reference< XStatement> xStmt(_xRs->getStatement(),UNO_QUERY);
                 [ #  # ]
     162         [ #  # ]:          0 :     if(xStmt.is())
     163 [ #  # ][ #  # ]:          0 :         xConnection = xStmt->getConnection();
                 [ #  # ]
     164                 :            :     else
     165                 :            :     {
     166 [ #  # ][ #  # ]:          0 :         Reference< XPreparedStatement> xPrepStmt(_xRs->getStatement(),UNO_QUERY);
                 [ #  # ]
     167 [ #  # ][ #  # ]:          0 :         xConnection = xPrepStmt->getConnection();
                 [ #  # ]
     168                 :            :     }
     169                 :            :     OSL_ENSURE(xConnection.is(),"No connection!");
     170         [ #  # ]:          0 :     if(_xAnalyzer.is())
     171                 :            :     {
     172                 :            :         try
     173                 :            :         {
     174         [ #  # ]:          0 :             Reference<XTablesSupplier> xTabSup(_xAnalyzer,UNO_QUERY);
     175                 :            :             OSL_ENSURE(xTabSup.is(),"ORowSet::execute composer isn't a tablesupplier!");
     176 [ #  # ][ #  # ]:          0 :             Reference<XNameAccess> xTables = xTabSup->getTables();
     177 [ #  # ][ #  # ]:          0 :             Sequence< ::rtl::OUString> aTableNames = xTables->getElementNames();
     178 [ #  # ][ #  # ]:          0 :             if ( aTableNames.getLength() > 1 && _rUpdateTableName.isEmpty() && bNeedKeySet )
         [ #  # ][ #  # ]
     179                 :            :             {// here we have a join or union and nobody told us which table to update, so we update them all
     180                 :          0 :                 m_nPrivileges = Privilege::SELECT|Privilege::DELETE|Privilege::INSERT|Privilege::UPDATE;
     181   [ #  #  #  # ]:          0 :                 OptimisticSet* pCursor = new OptimisticSet(m_aContext,xConnection,_xAnalyzer,_aParameterValueForCache,i_nMaxRows,m_nRowCount);
     182                 :          0 :                 m_pCacheSet = pCursor;
     183 [ #  # ][ #  # ]:          0 :                 m_xCacheSet = m_pCacheSet;
     184                 :            :                 try
     185                 :            :                 {
     186         [ #  # ]:          0 :                     m_pCacheSet->construct(_xRs,i_sRowSetFilter);
     187         [ #  # ]:          0 :                     if ( pCursor->isReadOnly() )
     188                 :          0 :                         m_nPrivileges = Privilege::SELECT;
     189         [ #  # ]:          0 :                     m_aKeyColumns = pCursor->getJoinedKeyColumns();
     190                 :            :                     return;
     191                 :            :                 }
     192         [ #  # ]:          0 :                 catch(const Exception&)
     193                 :            :                 {
     194                 :            :                 }
     195                 :          0 :                 m_pCacheSet = NULL;
     196                 :          0 :                 m_xCacheSet.clear();
     197                 :            :             }
     198                 :            :             else
     199                 :            :             {
     200 [ #  # ][ #  # ]:          0 :                 if(!_rUpdateTableName.isEmpty() && xTables->hasByName(_rUpdateTableName))
         [ #  # ][ #  # ]
                 [ #  # ]
     201 [ #  # ][ #  # ]:          0 :                     xTables->getByName(_rUpdateTableName) >>= m_aUpdateTable;
                 [ #  # ]
     202 [ #  # ][ #  # ]:          0 :                 else if(xTables->getElementNames().getLength())
         [ #  # ][ #  # ]
     203                 :            :                 {
     204 [ #  # ][ #  # ]:          0 :                     aUpdateTableName = xTables->getElementNames()[0];
         [ #  # ][ #  # ]
     205 [ #  # ][ #  # ]:          0 :                     xTables->getByName(aUpdateTableName) >>= m_aUpdateTable;
                 [ #  # ]
     206                 :            :                 }
     207         [ #  # ]:          0 :                 Reference<XIndexAccess> xIndexAccess(xTables,UNO_QUERY);
     208         [ #  # ]:          0 :                 if(xIndexAccess.is())
     209 [ #  # ][ #  # ]:          0 :                     nTablesCount = xIndexAccess->getCount();
     210                 :            :                 else
     211 [ #  # ][ #  # ]:          0 :                     nTablesCount = xTables->getElementNames().getLength();
                 [ #  # ]
     212                 :            : 
     213 [ #  # ][ #  # ]:          0 :                 if(m_aUpdateTable.is() && nTablesCount < 3) // for we can't handle more than 2 tables in our keyset
                 [ #  # ]
     214                 :            :                 {
     215         [ #  # ]:          0 :                     Reference<XPropertySet> xSet(m_aUpdateTable,UNO_QUERY);
     216         [ #  # ]:          0 :                     const Reference<XNameAccess> xPrimaryKeyColumns = dbtools::getPrimaryKeyColumns_throw(xSet);
     217         [ #  # ]:          0 :                     if ( xPrimaryKeyColumns.is() )
     218                 :            :                     {
     219         [ #  # ]:          0 :                         Reference<XColumnsSupplier> xColSup(_xAnalyzer,UNO_QUERY);
     220         [ #  # ]:          0 :                         if ( xColSup.is() )
     221                 :            :                         {
     222 [ #  # ][ #  # ]:          0 :                             Reference<XNameAccess> xSelColumns = xColSup->getColumns();
     223 [ #  # ][ #  # ]:          0 :                             Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
     224 [ #  # ][ #  # ]:          0 :                             SelectColumnsMetaData aColumnNames(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers() ? true : false);
         [ #  # ][ #  # ]
                 [ #  # ]
     225 [ #  # ][ #  # ]:          0 :                             ::dbaccess::getColumnPositions(xSelColumns,xPrimaryKeyColumns->getElementNames(),aUpdateTableName,aColumnNames);
         [ #  # ][ #  # ]
     226 [ #  # ][ #  # ]:          0 :                             bAllKeysFound = !aColumnNames.empty() && sal_Int32(aColumnNames.size()) == xPrimaryKeyColumns->getElementNames().getLength();
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     227                 :          0 :                         }
     228                 :          0 :                     }
     229                 :          0 :                 }
     230 [ #  # ][ #  # ]:          0 :             }
         [ #  # ][ #  # ]
                 [ #  # ]
     231                 :            :         }
     232         [ #  # ]:          0 :         catch(Exception&)
     233                 :            :         {
     234                 :            :         }
     235                 :            :     }
     236                 :            : 
     237                 :            :     // first check if resultset is bookmarkable
     238         [ #  # ]:          0 :     if(!bNeedKeySet)
     239                 :            :     {
     240                 :            :         try
     241                 :            :         {
     242         [ #  # ]:          0 :             m_pCacheSet = new OBookmarkSet(i_nMaxRows);
     243 [ #  # ][ #  # ]:          0 :             m_xCacheSet = m_pCacheSet;
     244         [ #  # ]:          0 :             m_pCacheSet->construct(_xRs,i_sRowSetFilter);
     245                 :            : 
     246                 :            :             // check privileges
     247                 :          0 :             m_nPrivileges = Privilege::SELECT;
     248 [ #  # ][ #  # ]:          0 :             if(Reference<XResultSetUpdate>(_xRs,UNO_QUERY).is())  // this interface is optional so we have to check it
     249                 :            :             {
     250         [ #  # ]:          0 :                 Reference<XPropertySet> xTable(m_aUpdateTable,UNO_QUERY);
     251 [ #  # ][ #  # ]:          0 :                 if(xTable.is() && xTable->getPropertySetInfo()->hasPropertyByName(PROPERTY_PRIVILEGES))
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  #  
             #  #  #  # ]
     252                 :            :                 {
     253                 :          0 :                     m_nPrivileges = 0;
     254 [ #  # ][ #  # ]:          0 :                     xTable->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges;
                 [ #  # ]
     255         [ #  # ]:          0 :                     if(!m_nPrivileges)
     256                 :          0 :                         m_nPrivileges = Privilege::SELECT;
     257         [ #  # ]:          0 :                 }
     258                 :            :             }
     259                 :            :         }
     260         [ #  # ]:          0 :         catch(const SQLException&)
     261                 :            :         {
     262                 :          0 :             bNeedKeySet = sal_True;
     263                 :            :         }
     264                 :            : 
     265                 :            :     }
     266         [ #  # ]:          0 :     if(bNeedKeySet)
     267                 :            :     {
     268                 :            :         // need to check if we could handle this select clause
     269 [ #  # ][ #  # ]:          0 :         bAllKeysFound = bAllKeysFound && (nTablesCount == 1 || checkJoin(xConnection,_xAnalyzer,aUpdateTableName));
         [ #  # ][ #  # ]
     270                 :            : 
     271         [ #  # ]:          0 :         if(!bAllKeysFound )
     272                 :            :         {
     273         [ #  # ]:          0 :             if ( bBookmarkable )
     274                 :            :             {
     275                 :            :                 // here I know that we have a read only bookmarkable cursor
     276 [ #  # ][ #  # ]:          0 :                 _xRs->beforeFirst();
     277                 :          0 :                 m_nPrivileges = Privilege::SELECT;
     278         [ #  # ]:          0 :                 m_pCacheSet = new WrappedResultSet(i_nMaxRows);
     279 [ #  # ][ #  # ]:          0 :                 m_xCacheSet = m_pCacheSet;
     280         [ #  # ]:          0 :                 m_pCacheSet->construct(_xRs,i_sRowSetFilter);
     281                 :            :                 return;
     282                 :            :             }
     283         [ #  # ]:          0 :             m_pCacheSet = new OStaticSet(i_nMaxRows);
     284 [ #  # ][ #  # ]:          0 :             m_xCacheSet = m_pCacheSet;
     285         [ #  # ]:          0 :             m_pCacheSet->construct(_xRs,i_sRowSetFilter);
     286                 :          0 :             m_nPrivileges = Privilege::SELECT;
     287                 :            :         }
     288                 :            :         else
     289                 :            :         {
     290 [ #  # ][ #  # ]:          0 :             Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
     291 [ #  # ][ #  # ]:          0 :             SelectColumnsMetaData aColumnNames(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers() ? true : false);
         [ #  # ][ #  # ]
                 [ #  # ]
     292         [ #  # ]:          0 :             Reference<XColumnsSupplier> xColSup(_xAnalyzer,UNO_QUERY);
     293 [ #  # ][ #  # ]:          0 :             Reference<XNameAccess> xSelColumns  = xColSup->getColumns();
     294 [ #  # ][ #  # ]:          0 :             Reference<XNameAccess> xColumns     = m_aUpdateTable->getColumns();
     295 [ #  # ][ #  # ]:          0 :             ::dbaccess::getColumnPositions(xSelColumns,xColumns->getElementNames(),aUpdateTableName,aColumnNames);
         [ #  # ][ #  # ]
     296                 :            : 
     297                 :            :             // check privileges
     298                 :          0 :             m_nPrivileges = Privilege::SELECT;
     299                 :          0 :             sal_Bool bNoInsert = sal_False;
     300                 :            : 
     301 [ #  # ][ #  # ]:          0 :             Sequence< ::rtl::OUString> aNames(xColumns->getElementNames());
     302                 :          0 :             const ::rtl::OUString* pIter    = aNames.getConstArray();
     303                 :          0 :             const ::rtl::OUString* pEnd     = pIter + aNames.getLength();
     304         [ #  # ]:          0 :             for(;pIter != pEnd;++pIter)
     305                 :            :             {
     306 [ #  # ][ #  # ]:          0 :                 Reference<XPropertySet> xColumn(xColumns->getByName(*pIter),UNO_QUERY);
                 [ #  # ]
     307                 :            :                 OSL_ENSURE(xColumn.is(),"Column in table is null!");
     308         [ #  # ]:          0 :                 if(xColumn.is())
     309                 :            :                 {
     310                 :          0 :                     sal_Int32 nNullable = 0;
     311 [ #  # ][ #  # ]:          0 :                     xColumn->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullable;
                 [ #  # ]
     312 [ #  # ][ #  # ]:          0 :                     if(nNullable == ColumnValue::NO_NULLS && aColumnNames.find(*pIter) == aColumnNames.end())
         [ #  # ][ #  # ]
           [ #  #  #  #  
           #  # ][ #  # ]
     313                 :            :                     { // we found a column where null is not allowed so we can't insert new values
     314                 :          0 :                         bNoInsert = sal_True;
     315                 :            :                         break; // one column is enough
     316                 :            :                     }
     317                 :            :                 }
     318         [ #  # ]:          0 :             }
     319                 :            : 
     320         [ #  # ]:          0 :             OKeySet* pKeySet = new OKeySet(m_aUpdateTable,xUpdateTableKeys,aUpdateTableName ,_xAnalyzer,_aParameterValueForCache,i_nMaxRows,m_nRowCount);
     321                 :            :             try
     322                 :            :             {
     323                 :          0 :                 m_pCacheSet = pKeySet;
     324 [ #  # ][ #  # ]:          0 :                 m_xCacheSet = m_pCacheSet;
     325         [ #  # ]:          0 :                 pKeySet->construct(_xRs,i_sRowSetFilter);
     326                 :            : 
     327 [ #  # ][ #  # ]:          0 :                 if(Reference<XResultSetUpdate>(_xRs,UNO_QUERY).is())  // this interface is optional so we have to check it
     328                 :            :                 {
     329         [ #  # ]:          0 :                     Reference<XPropertySet> xTable(m_aUpdateTable,UNO_QUERY);
     330 [ #  # ][ #  # ]:          0 :                     if(xTable.is() && xTable->getPropertySetInfo()->hasPropertyByName(PROPERTY_PRIVILEGES))
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  #  
             #  #  #  # ]
     331                 :            :                     {
     332                 :          0 :                         m_nPrivileges = 0;
     333 [ #  # ][ #  # ]:          0 :                         xTable->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges;
                 [ #  # ]
     334         [ #  # ]:          0 :                         if(!m_nPrivileges)
     335                 :          0 :                             m_nPrivileges = Privilege::SELECT;
     336                 :          0 :                     }
     337                 :            :                 }
     338         [ #  # ]:          0 :                 if(bNoInsert)
     339                 :          0 :                     m_nPrivileges |= ~Privilege::INSERT; // remove the insert privilege
     340                 :            :             }
     341   [ #  #  #  # ]:          0 :             catch(const SQLException&)
     342                 :            :             {
     343                 :            :                 // we couldn't create a keyset here so we have to create a static cache
     344         [ #  # ]:          0 :                 if ( m_pCacheSet )
     345                 :          0 :                     m_pCacheSet = NULL;
     346         [ #  # ]:          0 :                 m_xCacheSet = NULL;
     347         [ #  # ]:          0 :                 m_pCacheSet = new OStaticSet(i_nMaxRows);
     348   [ #  #  #  # ]:          0 :                 m_xCacheSet = m_pCacheSet;
     349         [ #  # ]:          0 :                 m_pCacheSet->construct(_xRs,i_sRowSetFilter);
     350                 :          0 :                 m_nPrivileges = Privilege::SELECT;
     351         [ #  # ]:          0 :             }
     352                 :            :         }
     353                 :            : 
     354                 :            :     }
     355                 :            :     // last check
     356 [ #  # ][ #  # ]:          0 :     if(!bAllKeysFound && xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_RESULTSETCONCURRENCY) &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  #  
                   #  # ]
     357 [ #  # ][ #  # ]:          0 :         ::comphelper::getINT32(xProp->getPropertyValue(PROPERTY_RESULTSETCONCURRENCY)) == ResultSetConcurrency::READ_ONLY)
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  # ]
     358 [ #  # ][ #  # ]:         40 :         m_nPrivileges = Privilege::SELECT;
         [ #  # ][ #  # ]
         [ +  - ][ -  + ]
     359                 :            : }
     360                 :            : 
     361 [ +  - ][ +  - ]:         40 : ORowSetCache::~ORowSetCache()
     362                 :            : {
     363                 :         40 :     m_pCacheSet = NULL;
     364         [ +  - ]:         40 :     m_xCacheSet = NULL;
     365         [ +  - ]:         40 :     if(m_pMatrix)
     366                 :            :     {
     367                 :         40 :         m_pMatrix->clear();
     368         [ +  - ]:         40 :         delete m_pMatrix;
     369                 :            :     }
     370                 :            : 
     371         [ +  - ]:         40 :     if(m_pInsertMatrix)
     372                 :            :     {
     373                 :         40 :         m_pInsertMatrix->clear();
     374         [ +  - ]:         40 :         delete m_pInsertMatrix;
     375                 :            :     }
     376 [ +  - ][ +  - ]:         40 :     m_xSet          = WeakReference< XResultSet>();
                 [ +  - ]
     377         [ +  - ]:         40 :     m_xMetaData     = NULL;
     378         [ +  - ]:         40 :     m_aUpdateTable  = NULL;
     379                 :            : 
     380                 :            :     DBG_DTOR(ORowSetCache,NULL);
     381                 :         40 : }
     382                 :            : 
     383                 :         46 : void ORowSetCache::setFetchSize(sal_Int32 _nSize)
     384                 :            : {
     385         [ -  + ]:         46 :     if(_nSize == m_nFetchSize)
     386                 :         46 :         return;
     387                 :            : 
     388                 :         46 :     m_nFetchSize = _nSize;
     389         [ +  + ]:         46 :     if(!m_pMatrix)
     390                 :            :     {
     391         [ +  - ]:         40 :         m_pMatrix = new ORowSetMatrix(_nSize);
     392                 :         40 :         m_aMatrixIter = m_pMatrix->end();
     393                 :         40 :         m_aMatrixEnd = m_pMatrix->end();
     394                 :            : 
     395         [ +  - ]:         40 :         m_pInsertMatrix = new ORowSetMatrix(1); // a little bit overkill but ??? :-)
     396                 :         40 :         m_aInsertRow    = m_pInsertMatrix->end();
     397                 :            :     }
     398                 :            :     else
     399                 :            :     {
     400                 :            :         // now correct the iterator in our iterator vector
     401         [ +  - ]:          6 :         ::std::vector<sal_Int32> aPositions;
     402         [ +  - ]:          6 :         ::std::map<sal_Int32,sal_Bool> aCacheIterToChange;
     403                 :            :         // first get the positions where they stand now
     404                 :          6 :         ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin();
     405                 :          6 :         ORowSetCacheMap::iterator aCacheEnd = m_aCacheIterators.end();
     406         [ +  + ]:         12 :         for(;aCacheIter != aCacheEnd;++aCacheIter)
     407                 :            :         {
     408         [ +  - ]:          6 :             aCacheIterToChange[aCacheIter->first] = sal_False;
     409 [ +  - ][ +  + ]:          6 :             if ( !aCacheIter->second.pRowSet->isInsertRow()
                 [ +  + ]
     410                 :          6 :                 /*&& aCacheIter->second.aIterator != m_pMatrix->end()*/ && !m_bModified )
     411                 :            :             {
     412         [ +  - ]:          4 :                 ptrdiff_t nDist = (aCacheIter->second.aIterator - m_pMatrix->begin());
     413         [ +  - ]:          4 :                 aPositions.push_back(nDist);
     414         [ +  - ]:          4 :                 aCacheIterToChange[aCacheIter->first] = sal_True;
     415                 :            :             }
     416                 :            :         }
     417         [ +  - ]:          6 :         sal_Int32 nKeyPos = (m_aMatrixIter - m_pMatrix->begin());
     418         [ +  - ]:          6 :         m_pMatrix->resize(_nSize);
     419                 :            : 
     420         [ +  - ]:          6 :         if ( nKeyPos < _nSize )
     421         [ +  - ]:          6 :             m_aMatrixIter = m_pMatrix->begin() + nKeyPos;
     422                 :            :         else
     423                 :          0 :             m_aMatrixIter = m_pMatrix->end();
     424                 :          6 :         m_aMatrixEnd = m_pMatrix->end();
     425                 :            : 
     426                 :            :         // now adjust their positions because a resize invalidates all iterators
     427         [ +  - ]:          6 :         ::std::vector<sal_Int32>::const_iterator aIter = aPositions.begin();
     428         [ +  - ]:          6 :         ::std::map<sal_Int32,sal_Bool>::const_iterator aPosChangeIter = aCacheIterToChange.begin();
     429 [ +  - ][ +  - ]:         24 :         for(    aCacheIter = m_aCacheIterators.begin();
                 [ +  + ]
     430         [ +  - ]:         12 :                 aPosChangeIter != aCacheIterToChange.end();
     431                 :            :                 ++aPosChangeIter,++aCacheIter)
     432                 :            :         {
     433 [ +  - ][ +  + ]:          6 :             if ( aPosChangeIter->second )
     434                 :            :             {
     435                 :            :                 CHECK_MATRIX_POS(*aIter);
     436 [ +  - ][ +  - ]:          4 :                 if ( *aIter < _nSize )
     437 [ +  - ][ +  - ]:          4 :                     aCacheIter->second.aIterator = m_pMatrix->begin() + *aIter++;
                 [ +  - ]
     438                 :            :                 else
     439                 :          0 :                     aCacheIter->second.aIterator = m_pMatrix->end();
     440                 :            :             }
     441                 :          6 :         }
     442                 :            :     }
     443         [ +  + ]:         46 :     if(!m_nPosition)
     444                 :            :     {
     445                 :         40 :         sal_Int32 nNewSt = 0;
     446         [ +  - ]:         40 :         fillMatrix(nNewSt,_nSize);
     447                 :            :         OSL_ENSURE(nNewSt == 0, "fillMatrix set new start to unexpected value");
     448                 :         40 :         m_nStartPos = 0;
     449                 :         40 :         m_nEndPos = _nSize;
     450                 :            :     }
     451 [ +  - ][ +  - ]:          6 :     else if (m_nStartPos < m_nPosition && m_nPosition <= m_nEndPos)
     452                 :            :     {
     453                 :          6 :         sal_Int32 nNewSt = -1;
     454                 :          6 :         _nSize += m_nStartPos;
     455         [ +  - ]:          6 :         fillMatrix(nNewSt, _nSize);
     456         [ +  - ]:          6 :         if (nNewSt >= 0)
     457                 :            :         {
     458                 :          6 :             m_nStartPos = nNewSt;
     459                 :          6 :             m_nEndPos =  _nSize;
     460         [ +  - ]:          6 :             m_aMatrixIter = calcPosition();
     461                 :            :         }
     462                 :            :         else
     463                 :            :         {
     464                 :          0 :             m_nEndPos = m_nStartPos + m_nFetchSize;
     465                 :          6 :         }
     466                 :            :     }
     467                 :            :     else
     468                 :            :     {
     469                 :            :         OSL_FAIL("m_nPosition not between m_nStartPos and m_nEndpos");
     470                 :            :         // try to repair
     471                 :          0 :         moveWindow();
     472                 :          0 :         m_aMatrixIter = calcPosition();
     473                 :            :     }
     474                 :            : }
     475                 :            : 
     476                 :            : // XResultSetMetaDataSupplier
     477                 :        572 : Reference< XResultSetMetaData > ORowSetCache::getMetaData(  )
     478                 :            : {
     479                 :        572 :     return m_xMetaData;
     480                 :            : }
     481                 :            : 
     482                 :        272 : Any lcl_getBookmark(ORowSetValue& i_aValue,OCacheSet* i_pCacheSet)
     483                 :            : {
     484         [ -  + ]:        272 :     switch ( i_aValue.getTypeKind() )
     485                 :            :     {
     486                 :            :         case DataType::TINYINT:
     487                 :            :         case DataType::SMALLINT:
     488                 :            :         case DataType::INTEGER:
     489         [ #  # ]:          0 :             return makeAny((sal_Int32)i_aValue);
     490                 :            :         default:
     491 [ +  - ][ -  + ]:        272 :             if ( i_pCacheSet && i_aValue.isNull())
                 [ -  + ]
     492         [ #  # ]:          0 :                 i_aValue = i_pCacheSet->getBookmark();
     493                 :        272 :             return i_aValue.getAny();
     494                 :            :     }
     495                 :            : }
     496                 :            : 
     497                 :            : // ::com::sun::star::sdbcx::XRowLocate
     498                 :        272 : Any ORowSetCache::getBookmark(  )
     499                 :            : {
     500         [ -  + ]:        272 :     if(m_bAfterLast)
     501 [ #  # ][ #  # ]:          0 :         throwFunctionSequenceException(m_xSet.get());
     502                 :            : 
     503 [ +  - ][ +  - ]:        272 :     if ( m_aMatrixIter >= m_pMatrix->end() || m_aMatrixIter < m_pMatrix->begin() || !(*m_aMatrixIter).is())
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ -  +  
             #  #  #  # ]
     504                 :            :     {
     505                 :          0 :         return Any(); // this is allowed here because the rowset knowns what it is doing
     506                 :            :     }
     507                 :            : 
     508                 :        272 :     return lcl_getBookmark(((*m_aMatrixIter)->get())[0],m_pCacheSet);
     509                 :            : }
     510                 :            : 
     511                 :        398 : sal_Bool ORowSetCache::moveToBookmark( const Any& bookmark )
     512                 :            : {
     513         [ +  - ]:        398 :     if ( m_pCacheSet->moveToBookmark(bookmark) )
     514                 :            :     {
     515                 :        398 :         m_bBeforeFirst = sal_False;
     516                 :        398 :         m_nPosition = m_pCacheSet->getRow();
     517                 :            : 
     518                 :        398 :         checkPositionFlags();
     519                 :            : 
     520         [ +  - ]:        398 :         if(!m_bAfterLast)
     521                 :            :         {
     522                 :        398 :             moveWindow();
     523                 :        398 :             checkPositionFlags();
     524         [ +  - ]:        398 :             if ( !m_bAfterLast )
     525                 :            :             {
     526                 :        398 :                 m_aMatrixIter = calcPosition();
     527                 :            :                 OSL_ENSURE(m_aMatrixIter->is(),"Iterator after moveToBookmark not valid");
     528                 :            :             }
     529                 :            :             else
     530                 :          0 :                 m_aMatrixIter = m_pMatrix->end();
     531                 :            :         }
     532                 :            :         else
     533                 :          0 :             m_aMatrixIter = m_pMatrix->end();
     534                 :            :     }
     535                 :            :     else
     536                 :          0 :         return sal_False;
     537                 :            : 
     538 [ +  - ][ +  - ]:        398 :     return m_aMatrixIter != m_pMatrix->end() && (*m_aMatrixIter).is();
         [ +  - ][ +  - ]
                 [ #  # ]
     539                 :            : }
     540                 :            : 
     541                 :          2 : sal_Bool ORowSetCache::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows )
     542                 :            : {
     543                 :          2 :     sal_Bool bRet( moveToBookmark( bookmark ) );
     544         [ +  - ]:          2 :     if ( bRet )
     545                 :            :     {
     546                 :          2 :         m_nPosition = m_pCacheSet->getRow() + rows;
     547                 :          2 :         absolute(m_nPosition);
     548                 :            : 
     549 [ +  - ][ +  - ]:          2 :         bRet = m_aMatrixIter != m_pMatrix->end() && (*m_aMatrixIter).is();
         [ +  - ][ #  # ]
                 [ +  - ]
     550                 :            :     }
     551                 :            : 
     552                 :          2 :     return bRet;
     553                 :            : }
     554                 :            : 
     555                 :         68 : sal_Int32 ORowSetCache::compareBookmarks( const Any& _first, const Any& _second )
     556                 :            : {
     557 [ +  - ][ +  - ]:         68 :     return (!_first.hasValue() || !_second.hasValue()) ? CompareBookmark::NOT_COMPARABLE : m_pCacheSet->compareBookmarks(_first,_second);
     558                 :            : }
     559                 :            : 
     560                 :          2 : sal_Bool ORowSetCache::hasOrderedBookmarks(  )
     561                 :            : {
     562                 :          2 :     return m_pCacheSet->hasOrderedBookmarks();
     563                 :            : }
     564                 :            : 
     565                 :          4 : sal_Int32 ORowSetCache::hashBookmark( const Any& bookmark )
     566                 :            : {
     567                 :          4 :     return m_pCacheSet->hashBookmark(bookmark);
     568                 :            : }
     569                 :            : 
     570                 :            : // XRowUpdate
     571                 :          0 : void ORowSetCache::updateNull(sal_Int32 columnIndex,ORowSetValueVector::Vector& io_aRow
     572                 :            :                               ,::std::vector<sal_Int32>& o_ChangedColumns
     573                 :            :                               )
     574                 :            : {
     575                 :          0 :     checkUpdateConditions(columnIndex);
     576                 :            : 
     577                 :          0 :     ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get());
     578         [ #  # ]:          0 :     if ( !rInsert[columnIndex].isNull() )
     579                 :            :     {
     580                 :          0 :         rInsert[columnIndex].setBound(sal_True);
     581                 :          0 :         rInsert[columnIndex].setNull();
     582                 :          0 :         rInsert[columnIndex].setModified();
     583                 :          0 :         io_aRow[columnIndex].setNull();
     584                 :            : 
     585                 :          0 :         m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns);
     586                 :          0 :         impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns);
     587                 :            :     }
     588                 :          0 : }
     589                 :            : 
     590                 :         12 : void ORowSetCache::updateValue(sal_Int32 columnIndex,const ORowSetValue& x
     591                 :            :                                ,ORowSetValueVector::Vector& io_aRow
     592                 :            :                                ,::std::vector<sal_Int32>& o_ChangedColumns
     593                 :            :                                )
     594                 :            : {
     595                 :         12 :     checkUpdateConditions(columnIndex);
     596                 :            : 
     597                 :         12 :     ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get());
     598         [ +  - ]:         12 :     if ( rInsert[columnIndex] != x )
     599                 :            :     {
     600                 :         12 :         rInsert[columnIndex].setBound(sal_True);
     601                 :         12 :         rInsert[columnIndex] = x;
     602                 :         12 :         rInsert[columnIndex].setModified();
     603                 :         12 :         io_aRow[columnIndex] = rInsert[columnIndex];
     604                 :            : 
     605                 :         12 :         m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns);
     606                 :         12 :         impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns);
     607                 :            :     }
     608                 :         12 : }
     609                 :            : 
     610                 :          0 : void ORowSetCache::updateCharacterStream( sal_Int32 columnIndex, const Reference< ::com::sun::star::io::XInputStream >& x
     611                 :            :                                          , sal_Int32 length,ORowSetValueVector::Vector& io_aRow
     612                 :            :                                          ,::std::vector<sal_Int32>& o_ChangedColumns
     613                 :            :                                          )
     614                 :            : {
     615         [ #  # ]:          0 :     checkUpdateConditions(columnIndex);
     616                 :            : 
     617         [ #  # ]:          0 :     Sequence<sal_Int8> aSeq;
     618         [ #  # ]:          0 :     if(x.is())
     619 [ #  # ][ #  # ]:          0 :         x->readBytes(aSeq,length);
     620                 :            : 
     621                 :          0 :     ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get());
     622         [ #  # ]:          0 :     rInsert[columnIndex].setBound(sal_True);
     623 [ #  # ][ #  # ]:          0 :     rInsert[columnIndex] = aSeq;
     624         [ #  # ]:          0 :     rInsert[columnIndex].setModified();
     625 [ #  # ][ #  # ]:          0 :     io_aRow[columnIndex] = makeAny(x);
                 [ #  # ]
     626                 :            : 
     627         [ #  # ]:          0 :     m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns);
     628 [ #  # ][ #  # ]:          0 :     impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns);
     629                 :          0 : }
     630                 :            : 
     631                 :          0 : void ORowSetCache::updateObject( sal_Int32 columnIndex, const Any& x
     632                 :            :                                 ,ORowSetValueVector::Vector& io_aRow
     633                 :            :                                 ,::std::vector<sal_Int32>& o_ChangedColumns
     634                 :            :                                 )
     635                 :            : {
     636         [ #  # ]:          0 :     checkUpdateConditions(columnIndex);
     637                 :            : 
     638                 :          0 :     ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get());
     639                 :          0 :     ORowSetValue aTemp;
     640         [ #  # ]:          0 :     aTemp.fill(x);
     641 [ #  # ][ #  # ]:          0 :     if ( rInsert[columnIndex] != aTemp )
                 [ #  # ]
     642                 :            :     {
     643         [ #  # ]:          0 :         rInsert[columnIndex].setBound(sal_True);
     644 [ #  # ][ #  # ]:          0 :         rInsert[columnIndex] = aTemp;
     645         [ #  # ]:          0 :         rInsert[columnIndex].setModified();
     646 [ #  # ][ #  # ]:          0 :         io_aRow[columnIndex] = rInsert[columnIndex];
                 [ #  # ]
     647                 :            : 
     648         [ #  # ]:          0 :         m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns);
     649         [ #  # ]:          0 :         impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns);
     650         [ #  # ]:          0 :     }
     651                 :          0 : }
     652                 :            : 
     653                 :          0 : void ORowSetCache::updateNumericObject( sal_Int32 columnIndex, const Any& x, sal_Int32 /*scale*/
     654                 :            :                                        ,ORowSetValueVector::Vector& io_aRow
     655                 :            :                                        ,::std::vector<sal_Int32>& o_ChangedColumns
     656                 :            :                                        )
     657                 :            : {
     658         [ #  # ]:          0 :     checkUpdateConditions(columnIndex);
     659                 :            : 
     660                 :          0 :     ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get());
     661                 :          0 :     ORowSetValue aTemp;
     662         [ #  # ]:          0 :     aTemp.fill(x);
     663 [ #  # ][ #  # ]:          0 :     if ( rInsert[columnIndex] != aTemp )
                 [ #  # ]
     664                 :            :     {
     665         [ #  # ]:          0 :         rInsert[columnIndex].setBound(sal_True);
     666 [ #  # ][ #  # ]:          0 :         rInsert[columnIndex] = aTemp;
     667         [ #  # ]:          0 :         rInsert[columnIndex].setModified();
     668 [ #  # ][ #  # ]:          0 :         io_aRow[columnIndex] = rInsert[columnIndex];
                 [ #  # ]
     669                 :            : 
     670         [ #  # ]:          0 :         m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns);
     671         [ #  # ]:          0 :         impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns);
     672         [ #  # ]:          0 :     }
     673                 :          0 : }
     674                 :            : 
     675                 :            : // XResultSet
     676                 :        132 : sal_Bool ORowSetCache::next(  )
     677                 :            : {
     678         [ +  - ]:        132 :     if(!isAfterLast())
     679                 :            :     {
     680                 :        132 :         m_bBeforeFirst = sal_False;
     681                 :        132 :         ++m_nPosition;
     682                 :            : 
     683                 :            :         // after we increment the position we have to check if we are already after the last row
     684                 :        132 :         checkPositionFlags();
     685         [ +  + ]:        132 :         if(!m_bAfterLast)
     686                 :            :         {
     687                 :        124 :             moveWindow();
     688                 :            : 
     689                 :            :             OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!");
     690                 :        124 :             m_aMatrixIter = calcPosition();
     691                 :        124 :             checkPositionFlags();
     692                 :            :         }
     693                 :            :     }
     694                 :            : 
     695                 :        132 :     return !m_bAfterLast;
     696                 :            : }
     697                 :            : 
     698                 :        382 : sal_Bool ORowSetCache::isBeforeFirst(  )
     699                 :            : {
     700                 :        382 :     return m_bBeforeFirst;
     701                 :            : }
     702                 :            : 
     703                 :        654 : sal_Bool ORowSetCache::isAfterLast(  )
     704                 :            : {
     705                 :        654 :     return m_bAfterLast;
     706                 :            : }
     707                 :            : 
     708                 :         18 : sal_Bool ORowSetCache::isFirst(  )
     709                 :            : {
     710                 :         18 :     return m_nPosition == 1; // ask resultset for
     711                 :            : }
     712                 :            : 
     713                 :          4 : sal_Bool ORowSetCache::isLast(  )
     714                 :            : {
     715                 :          4 :     return m_nPosition == m_nRowCount;
     716                 :            : }
     717                 :            : 
     718                 :         18 : sal_Bool ORowSetCache::beforeFirst(  )
     719                 :            : {
     720         [ +  + ]:         18 :     if(!m_bBeforeFirst)
     721                 :            :     {
     722                 :          8 :         m_bAfterLast    = sal_False;
     723                 :          8 :         m_nPosition     = 0;
     724                 :          8 :         m_bBeforeFirst  = sal_True;
     725                 :          8 :         m_pCacheSet->beforeFirst();
     726                 :          8 :         moveWindow();
     727                 :          8 :         m_aMatrixIter = m_pMatrix->end();
     728                 :            :     }
     729                 :         18 :     return sal_True;
     730                 :            : }
     731                 :            : 
     732                 :         10 : sal_Bool ORowSetCache::afterLast(  )
     733                 :            : {
     734         [ +  - ]:         10 :     if(!m_bAfterLast)
     735                 :            :     {
     736                 :         10 :         m_bBeforeFirst = sal_False;
     737                 :         10 :         m_bAfterLast = sal_True;
     738                 :            : 
     739         [ -  + ]:         10 :         if(!m_bRowCountFinal)
     740                 :            :         {
     741                 :          0 :             m_pCacheSet->last_checked(sal_False);
     742                 :          0 :             m_bRowCountFinal = sal_True;
     743                 :          0 :             m_nRowCount = m_pCacheSet->getRow();// + 1 removed
     744                 :            :         }
     745                 :         10 :         m_pCacheSet->afterLast();
     746                 :            : 
     747                 :         10 :         m_nPosition = 0;
     748                 :         10 :         m_aMatrixIter = m_pMatrix->end();
     749                 :            :     }
     750                 :         10 :     return sal_True;
     751                 :            : }
     752                 :            : 
     753                 :         46 : sal_Bool ORowSetCache::fillMatrix(sal_Int32& _nNewStartPos, sal_Int32 &_nNewEndPos)
     754                 :            : {
     755                 :            :     OSL_ENSURE(_nNewStartPos != _nNewEndPos,"ORowSetCache::fillMatrix: StartPos and EndPos can not be equal!");
     756                 :            :     // If _nNewStartPos >= 0, then fill the whole window with new data
     757                 :            :     // Else if _nNewStartPos == -1, then fill only segment [m_nEndPos, _nNewEndPos)
     758                 :            :     // Else, undefined (invalid argument)
     759                 :            :     OSL_ENSURE( _nNewStartPos >= -1, "ORowSetCache::fillMatrix: invalid _nNewStartPos" );
     760                 :            : 
     761                 :         46 :     ORowSetMatrix::iterator aIter;
     762                 :            :     sal_Int32 i;
     763                 :            :     sal_Bool bCheck;
     764                 :            :     sal_Int32 requestedStartPos;
     765         [ +  + ]:         46 :     if ( _nNewStartPos == -1 )
     766                 :            :     {
     767         [ +  - ]:          6 :         aIter = m_pMatrix->begin() + (m_nEndPos - m_nStartPos);
     768                 :          6 :         i = m_nEndPos + 1;
     769                 :          6 :         requestedStartPos = m_nStartPos;
     770                 :            :     }
     771                 :            :     else
     772                 :            :     {
     773                 :         40 :         aIter = m_pMatrix->begin();
     774                 :         40 :         i = _nNewStartPos + 1;
     775                 :         40 :         requestedStartPos = _nNewStartPos;
     776                 :            :     }
     777         [ +  - ]:         46 :     bCheck = m_pCacheSet->absolute(i);
     778                 :            : 
     779                 :            : 
     780         [ +  - ]:        340 :     for(; i <= _nNewEndPos; ++i,++aIter)
     781                 :            :     {
     782         [ +  + ]:        340 :         if(bCheck)
     783                 :            :         {
     784         [ +  - ]:        294 :             if(!aIter->is())
     785 [ +  - ][ +  - ]:        294 :                 *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount());
         [ +  - ][ +  - ]
     786         [ +  - ]:        294 :             m_pCacheSet->fillValueRow(*aIter,i);
     787                 :            :         }
     788                 :            :         else
     789                 :            :         {   // there are no more rows found so we can fetch some before start
     790                 :            : 
     791         [ +  + ]:         46 :             if(!m_bRowCountFinal)
     792                 :            :             {
     793 [ +  - ][ +  + ]:         40 :                 if(m_pCacheSet->previous_checked(sal_False)) // because we stand after the last row
     794         [ +  - ]:         34 :                     m_nRowCount = m_pCacheSet->getRow(); // here we have the row count
     795         [ +  + ]:         40 :                 if(!m_nRowCount)
     796                 :          6 :                     m_nRowCount = i-1; // it can be that getRow return zero
     797                 :         40 :                 m_bRowCountFinal = sal_True;
     798                 :            :             }
     799                 :         46 :             const ORowSetMatrix::iterator aEnd = aIter;
     800                 :         46 :             ORowSetMatrix::iterator aRealEnd = m_pMatrix->end();
     801                 :            :             sal_Int32 nPos;
     802         [ -  + ]:         46 :             if (m_nRowCount >= m_nFetchSize)
     803                 :            :             {
     804                 :          0 :                 nPos = m_nRowCount - m_nFetchSize;
     805                 :            :             }
     806                 :            :             else
     807                 :            :             {
     808                 :         46 :                 nPos = 0;
     809                 :            :             }
     810                 :         46 :             _nNewStartPos = nPos;
     811                 :         46 :             _nNewEndPos = m_nRowCount;
     812                 :         46 :             ++nPos;
     813         [ +  - ]:         46 :             bCheck = m_pCacheSet->absolute(nPos);
     814                 :            : 
     815 [ +  + ][ -  + ]:         46 :             for(;bCheck && nPos <= requestedStartPos && aIter != aRealEnd; ++aIter, ++nPos)
         [ #  # ][ #  # ]
                 [ -  + ]
     816                 :            :             {
     817         [ #  # ]:          0 :                 if(!aIter->is())
     818 [ #  # ][ #  # ]:          0 :                     *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount());
         [ #  # ][ #  # ]
     819         [ #  # ]:          0 :                 m_pCacheSet->fillValueRow(*aIter, nPos);
     820         [ #  # ]:          0 :                 bCheck = m_pCacheSet->next();
     821                 :            :             }
     822 [ +  - ][ -  + ]:         46 :             if(aIter != aEnd)
     823         [ #  # ]:         46 :                 ::std::rotate(m_pMatrix->begin(),aEnd,aIter);
     824                 :            :             break;
     825                 :            :         }
     826         [ +  - ]:        294 :         bCheck = m_pCacheSet->next();
     827                 :            :     }
     828                 :            :     // we have to read one row forward to ensure that we know when we are on last row
     829                 :            :     // but only when we don't know it already
     830         [ -  + ]:         46 :     if(!m_bRowCountFinal)
     831                 :            :     {
     832 [ #  # ][ #  # ]:          0 :         if(!m_pCacheSet->next())
     833                 :            :         {
     834 [ #  # ][ #  # ]:          0 :             if(m_pCacheSet->previous_checked(sal_False)) // because we stand after the last row
     835         [ #  # ]:          0 :                 m_nRowCount = m_pCacheSet->getRow(); // here we have the row count
     836                 :          0 :             m_bRowCountFinal = sal_True;
     837                 :            :         }
     838                 :            :         else
     839         [ #  # ]:          0 :            m_nRowCount = std::max(i,m_nRowCount);
     840                 :            : 
     841                 :            :     }
     842                 :         46 :     return bCheck;
     843                 :            : }
     844                 :            : 
     845                 :            : // If m_nPosition is out of the current window,
     846                 :            : // move it and update m_nStartPos and m_nEndPos
     847                 :            : // Caller is responsible for updating m_aMatrixIter
     848                 :        606 : sal_Bool ORowSetCache::moveWindow()
     849                 :            : {
     850                 :            :     OSL_ENSURE(m_nStartPos >= 0,"ORowSetCache::moveWindow: m_nStartPos is less than 0!");
     851                 :            :     OSL_ENSURE(m_nEndPos >= m_nStartPos,"ORowSetCache::moveWindow: m_nStartPos not smaller than m_nEndPos");
     852                 :            :     OSL_ENSURE(m_nEndPos-m_nStartPos <= m_nFetchSize,"ORowSetCache::moveWindow: m_nStartPos and m_nEndPos too far apart");
     853                 :            : 
     854 [ +  + ][ +  + ]:        606 :     if ( m_nStartPos < m_nPosition && m_nPosition <= m_nEndPos )
     855                 :            :     {
     856                 :            :         // just move inside the window
     857                 :            :         OSL_ENSURE((m_nPosition - m_nStartPos) <= (sal_Int32)m_pMatrix->size(),"Position is behind end()!");
     858                 :            :         // make double plus sure that we have fetched that row
     859         [ +  - ]:        596 :         m_aMatrixIter = calcPosition();
     860                 :            :         OSL_ENSURE(m_aMatrixIter != m_pMatrix->end(), "New m_aMatrixIter is at end(), but should not.");
     861         [ +  + ]:        596 :         if(!m_aMatrixIter->is())
     862                 :            :         {
     863         [ +  - ]:          8 :             sal_Bool bOk( m_pCacheSet->absolute( m_nPosition ) );
     864         [ +  - ]:          8 :             if ( bOk )
     865                 :            :             {
     866 [ +  - ][ +  - ]:          8 :                 *m_aMatrixIter = new ORowSetValueVector(m_xMetaData->getColumnCount());
         [ +  - ][ +  - ]
     867         [ +  - ]:          8 :                 m_pCacheSet->fillValueRow(*m_aMatrixIter,m_nPosition);
     868                 :            :                 // we have to read one row forward to ensure that we know when we are on last row
     869                 :            :                 // but only when we don't know it already
     870         [ -  + ]:          8 :                 if ( !m_bRowCountFinal )
     871                 :            :                 {
     872         [ #  # ]:          0 :                     bOk = m_pCacheSet->absolute_checked( m_nPosition + 1,sal_False );
     873         [ #  # ]:          0 :                     if ( bOk )
     874         [ #  # ]:          0 :                         m_nRowCount = std::max(sal_Int32(m_nPosition+1),m_nRowCount);
     875                 :            :                 }
     876                 :            :             }
     877 [ -  + ][ #  # ]:          8 :             if(!bOk && !m_bRowCountFinal)
     878                 :            :             {
     879                 :            :                 // because we stand after the last row
     880 [ #  # ][ #  # ]:          0 :                 m_nRowCount = m_pCacheSet->previous_checked(sal_False) ? m_pCacheSet->getRow() : 0;
                 [ #  # ]
     881                 :          0 :                 m_bRowCountFinal = sal_True;
     882                 :            :             }
     883                 :            :         }
     884                 :        596 :         return sal_True;
     885                 :            :     }
     886                 :            : 
     887                 :         10 :     sal_Bool bRet = sal_True;
     888                 :            : 
     889                 :         10 :     sal_Int32 nDiff = (m_nFetchSize - 1) / 2;
     890                 :         10 :     sal_Int32 nNewStartPos  = (m_nPosition - nDiff) - 1; //m_nPosition is 1-based, but m_nStartPos is 0-based
     891                 :         10 :     sal_Int32 nNewEndPos    = nNewStartPos + m_nFetchSize;
     892                 :            : 
     893         [ +  - ]:         10 :     if ( nNewStartPos < 0 )
     894                 :            :     {
     895                 :            :         // The computed new window crashes through the floor (begins before first row);
     896                 :            :         // nNew*Pos has to be shifted by -nNewStartPos
     897                 :         10 :         nNewEndPos -= nNewStartPos;
     898                 :         10 :         nNewStartPos = 0;
     899                 :            :     }
     900                 :            : 
     901         [ -  + ]:         10 :     if ( nNewStartPos < m_nStartPos )
     902                 :            :     {   // need to fill data *before* m_nStartPos
     903         [ #  # ]:          0 :         if ( nNewEndPos > m_nStartPos )
     904                 :            :         {   // The two regions are overlapping.
     905                 :            :             // We'll first rotate the contents of m_pMatrix so that the overlap area
     906                 :            :             // is positioned right; in the old window it is at the beginning,
     907                 :            :             // it has to go to the end.
     908                 :            :             // then we fill in the rows between new and old start pos.
     909                 :            : 
     910                 :            :             sal_Bool bCheck;
     911         [ #  # ]:          0 :             bCheck = m_pCacheSet->absolute(nNewStartPos + 1);
     912                 :            : 
     913                 :            :             // m_nEndPos < nNewEndPos when window not filled (e.g. there are less rows in total than window size)
     914         [ #  # ]:          0 :             m_nEndPos = std::min(nNewEndPos, m_nEndPos);
     915                 :          0 :             const sal_Int32 nOverlapSize = m_nEndPos - m_nStartPos;
     916                 :          0 :             const sal_Int32 nStartPosOffset = m_nStartPos - nNewStartPos; // by how much m_nStartPos moves
     917                 :          0 :             m_nStartPos = nNewStartPos;
     918                 :            :             OSL_ENSURE( static_cast<ORowSetMatrix::size_type>(nOverlapSize) <= m_pMatrix->size(), "new window end is after end of cache matrix!" );
     919                 :            :             // the first position in m_pMatrix whose data we don't keep;
     920                 :            :             // content will be moved to m_pMatrix.begin()
     921         [ #  # ]:          0 :             ORowSetMatrix::iterator aEnd (m_pMatrix->begin() + nOverlapSize);
     922                 :            :             // the first unused position after we are done; it == m_pMatrix.end() if and only if the window is full
     923         [ #  # ]:          0 :             ORowSetMatrix::iterator aNewEnd (aEnd + nStartPosOffset);
     924                 :            :             // *m_pMatrix now looks like:
     925                 :            :             //   [0; nOverlapSize) i.e. [begin(); aEnd): data kept
     926                 :            :             //   [nOverlapSize; nOverlapSize + nStartPosOffet) i.e. [aEnd, aNewEnd): new data of positions < old m_nStartPos
     927                 :            :             //   [nOverlapSize + nStartPosOffet; size()) i.e. [aNewEnd, end()): unused
     928                 :            :             // Note that nOverlapSize + nStartPosOffet == m_nEndPos - m_nStartPos (new values)
     929                 :            :             // When we are finished:
     930                 :            :             //   [0; nStartPosOffset) i.e. [begin(); aEnd): new data of positions < old m_nStartPos
     931                 :            :             //   [nStartPosOffset; nOverlapSize + nStartPosOffet) i.e. [aEnd, aNewEnd): kept
     932                 :            :             //   [nOverlapSize + nStartPosOffet; size()) i.e. [aNewEnd, end()): unused
     933                 :            : 
     934         [ #  # ]:          0 :             if ( bCheck )
     935                 :            :             {
     936                 :            :                 {
     937                 :          0 :                     ORowSetMatrix::iterator aIter(aEnd);
     938                 :          0 :                     sal_Int32 nPos = m_nStartPos + 1;
     939 [ #  # ][ #  # ]:          0 :                     bCheck = fill(aIter, aNewEnd, nPos, bCheck);
     940                 :            :                 }
     941                 :            : 
     942         [ #  # ]:          0 :                 ::std::rotate(m_pMatrix->begin(), aEnd, aNewEnd);
     943                 :            :                 // now correct the iterator in our iterator vector
     944                 :            :                 //  rotateCacheIterator(aEnd-m_pMatrix->begin()); //can't be used because they decrement and here we need to increment
     945                 :          0 :                 ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin();
     946                 :          0 :                 const ORowSetCacheMap::const_iterator aCacheEnd  = m_aCacheIterators.end();
     947         [ #  # ]:          0 :                 for(;aCacheIter != aCacheEnd;++aCacheIter)
     948                 :            :                 {
     949 [ #  # ][ #  # ]:          0 :                     if ( !aCacheIter->second.pRowSet->isInsertRow()
         [ #  # ][ #  # ]
     950 [ #  # ][ #  # ]:          0 :                         && aCacheIter->second.aIterator != m_pMatrix->end() && !m_bModified )
                 [ #  # ]
     951                 :            :                     {
     952         [ #  # ]:          0 :                         const ptrdiff_t nDist = (aCacheIter->second.aIterator - m_pMatrix->begin());
     953         [ #  # ]:          0 :                         if ( nDist >= nOverlapSize )
     954                 :            :                         {
     955                 :            :                             // That's from outside the overlap area; invalidate iterator.
     956                 :          0 :                             aCacheIter->second.aIterator = m_pMatrix->end();
     957                 :            :                         }
     958                 :            :                         else
     959                 :            :                         {
     960                 :            :                             // Inside overlap area: move to correct position
     961                 :            :                             CHECK_MATRIX_POS( (nDist + nStartPosOffset) );
     962                 :          0 :                             aCacheIter->second.aIterator += nStartPosOffset;
     963                 :            :                             OSL_ENSURE(aCacheIter->second.aIterator >= m_pMatrix->begin()
     964                 :            :                                     && aCacheIter->second.aIterator < m_pMatrix->end(),"Iterator out of area!");
     965                 :            :                         }
     966                 :            :                     }
     967                 :            :                 }
     968                 :            :             }
     969                 :            :             else
     970                 :            :             { // normally this should never happen
     971                 :            :                 OSL_FAIL("What the hell is happen here!");
     972                 :          0 :                 return sal_False;
     973                 :            :             }
     974                 :            :         }
     975                 :            :         else
     976                 :            :         {// no rows can be reused so fill again
     977         [ #  # ]:          0 :             bRet = reFillMatrix(nNewStartPos,nNewEndPos);
     978                 :            :         }
     979                 :            :     }
     980                 :            : 
     981                 :            :     OSL_ENSURE(nNewStartPos >= m_nStartPos, "ORowSetCache::moveWindow internal error: new start pos before current start pos");
     982         [ +  - ]:         10 :     if ( m_nEndPos < nNewEndPos )
     983                 :            :     {   // need to fill data *after* m_nEndPos
     984         [ +  - ]:         10 :         if( nNewStartPos < m_nEndPos )
     985                 :            :         {   // The two regions are overlapping.
     986                 :         10 :             const sal_Int32 nRowsInCache = m_nEndPos - m_nStartPos;
     987         [ +  - ]:         10 :             if ( nRowsInCache < m_nFetchSize )
     988                 :            :             {
     989                 :            :                 // There is some unused space in *m_pMatrix; fill it
     990                 :            :                 CHECK_MATRIX_POS(nRowsInCache);
     991                 :         10 :                 sal_Int32 nPos = m_nEndPos + 1;
     992         [ +  - ]:         10 :                 sal_Bool bCheck = m_pCacheSet->absolute(nPos);
     993         [ +  - ]:         10 :                 ORowSetMatrix::iterator aIter = m_pMatrix->begin() + nRowsInCache;
     994         [ +  - ]:         10 :                 const sal_Int32 nRowsToFetch = std::min(nNewEndPos-m_nEndPos, m_nFetchSize-nRowsInCache);
     995 [ +  - ][ +  - ]:         10 :                 const ORowSetMatrix::const_iterator aEnd = aIter + nRowsToFetch;
     996         [ +  - ]:         10 :                 bCheck = fill(aIter, aEnd, nPos, bCheck);
     997                 :         10 :                 m_nEndPos = nPos - 1;
     998                 :            :                 OSL_ENSURE( (!bCheck && m_nEndPos <= nNewEndPos ) ||
     999                 :            :                             ( bCheck && m_nEndPos == nNewEndPos ),
    1000                 :            :                              "ORowSetCache::moveWindow opportunistic fetch-after-current-end went badly");
    1001                 :            :             }
    1002                 :            : 
    1003                 :            :             // À priori, the rows from begin() [inclusive] to (begin() + nNewStartPos - m_nStartPos) [exclusive]
    1004                 :            :             // have to be refilled with new to-be-fetched rows.
    1005                 :            :             // The rows behind this can be reused
    1006                 :         10 :             ORowSetMatrix::iterator aIter = m_pMatrix->begin();
    1007                 :         10 :             const sal_Int32 nNewStartPosInMatrix = nNewStartPos - m_nStartPos;
    1008                 :            :             CHECK_MATRIX_POS( nNewStartPosInMatrix );
    1009                 :            :             // first position we reuse
    1010 [ +  - ][ +  - ]:         10 :             const ORowSetMatrix::const_iterator aEnd  = m_pMatrix->begin() + nNewStartPosInMatrix;
    1011                 :            :             // End of used portion of the matrix. Is < m_pMatrix->end() if less data than window size
    1012         [ +  - ]:         10 :             ORowSetMatrix::iterator aDataEnd  = m_pMatrix->begin() + (m_nEndPos - m_nStartPos);
    1013                 :            : 
    1014                 :         10 :             sal_Int32 nPos = m_nEndPos + 1;
    1015         [ +  - ]:         10 :             sal_Bool bCheck = m_pCacheSet->absolute(nPos);
    1016         [ +  - ]:         10 :             bCheck = fill(aIter, aEnd, nPos, bCheck); // refill the region we don't need anymore
    1017                 :            :             //aIter and nPos are now the position *after* last filled in one!
    1018                 :            : 
    1019                 :            :             // bind end to front
    1020         [ -  + ]:         10 :             if(bCheck)
    1021                 :            :             {
    1022                 :            :                 OSL_ENSURE(aIter == aEnd, "fill() said went till end, but did not.");
    1023                 :            :                 // rotate the end to the front
    1024         [ #  # ]:          0 :                 ::std::rotate(m_pMatrix->begin(), aIter, aDataEnd);
    1025                 :            :                 // now correct the iterator in our iterator vector
    1026         [ #  # ]:          0 :                 rotateCacheIterator( nNewStartPosInMatrix );
    1027                 :          0 :                 m_nStartPos = nNewStartPos;
    1028                 :          0 :                 m_nEndPos = nNewEndPos;
    1029                 :            :                 // now I can say how many rows we have
    1030                 :            :                 // we have to read one row forward to ensure that we know when we are on last row
    1031                 :            :                 // but only when we don't know it already
    1032                 :          0 :                 sal_Bool bOk = sal_True;
    1033         [ #  # ]:          0 :                 if(!m_bRowCountFinal)
    1034         [ #  # ]:          0 :                     bOk = m_pCacheSet->next();
    1035         [ #  # ]:          0 :                 if(!bOk)
    1036                 :            :                 {
    1037         [ #  # ]:          0 :                     m_pCacheSet->previous_checked(sal_False); // because we stand after the last row
    1038                 :          0 :                     m_nRowCount      = nPos; // here we have the row count
    1039                 :            :                     OSL_ENSURE(nPos == m_pCacheSet->getRow(),"nPos is not valid!");
    1040                 :          0 :                     m_bRowCountFinal = sal_True;
    1041                 :            :                 }
    1042         [ #  # ]:          0 :                 else if(!m_bRowCountFinal)
    1043         [ #  # ]:          0 :                     m_nRowCount = std::max(nPos+1, m_nRowCount); //+1 because we successfully moved to row after nPos
    1044                 :            :                 else
    1045                 :            :                     OSL_ENSURE(m_nRowCount >= nPos, "Final m_nRowCount is smaller than row I moved to!");
    1046                 :            :             }
    1047                 :            :             else
    1048                 :            :             {   // the end was reached before or at end() so we can set the start before or at nNewStartPos
    1049                 :            :                 // and possibly keep more of m_pMatrix than planned.
    1050         [ +  - ]:         10 :                 const ORowSetMatrix::iterator::difference_type nFetchedRows  = aIter - m_pMatrix->begin();
    1051                 :            :                 // *m_pMatrix now looks like:
    1052                 :            :                 // [0; nFetchedRows) i.e. [begin(); aIter): newly fetched data for positions m_nEndPos to m_nEndPos+nFetchedRows
    1053                 :            :                 // [nFetchedRows; ???) i.e. [aIter; aDataEnd]: data to be kept for positions m_nStartPos+nFetchedRows to ???
    1054                 :            : 
    1055                 :         10 :                 nPos -= 1;
    1056                 :         10 :                 m_nStartPos += nFetchedRows;
    1057                 :         10 :                 m_nEndPos = nPos;
    1058         [ +  - ]:         10 :                 ::std::rotate(m_pMatrix->begin(), aIter, aDataEnd);
    1059                 :            :                 // now correct the iterator in our iterator vector
    1060         [ +  - ]:         10 :                 rotateCacheIterator( nFetchedRows );
    1061                 :            : 
    1062         [ -  + ]:         10 :                 if ( !m_bRowCountFinal )
    1063                 :            :                 {
    1064         [ #  # ]:          0 :                     m_pCacheSet->previous_checked(sal_False);                   // because we stand after the last row
    1065         [ #  # ]:          0 :                     m_nRowCount      = std::max(m_nRowCount, nPos);    // here we have the row count
    1066                 :            :                     OSL_ENSURE(nPos == m_pCacheSet->getRow(),"nPos isn't valid!");
    1067                 :          0 :                     m_bRowCountFinal = sal_True;
    1068                 :            :                 }
    1069                 :            : 
    1070                 :            :             }
    1071                 :            :             // here we need only to check if the beginning row is valid. If not we have to fetch it.
    1072         [ -  + ]:         10 :             if(!m_pMatrix->begin()->is())
    1073                 :            :             {
    1074                 :          0 :                 aIter = m_pMatrix->begin();
    1075                 :            : 
    1076                 :          0 :                 nPos    = m_nStartPos + 1;
    1077         [ #  # ]:          0 :                 bCheck  = m_pCacheSet->absolute_checked(nPos, sal_True);
    1078 [ #  # ][ #  # ]:         10 :                 for(; !aIter->is() && bCheck;++aIter, ++nPos)
                 [ #  # ]
    1079                 :            :                 {
    1080                 :            :                     OSL_ENSURE(aIter != m_pMatrix->end(),"Invalid iterator");
    1081                 :            : 
    1082 [ #  # ][ #  # ]:          0 :                     *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount());
         [ #  # ][ #  # ]
    1083         [ #  # ]:          0 :                     m_pCacheSet->fillValueRow(*aIter, nPos);
    1084                 :            : 
    1085         [ #  # ]:          0 :                     bCheck = m_pCacheSet->next();
    1086                 :            :                 }
    1087                 :            :             }
    1088                 :            :         }
    1089                 :            :         else // no rows can be reused so fill again
    1090         [ #  # ]:          0 :             bRet = reFillMatrix(nNewStartPos,nNewEndPos);
    1091                 :            :     }
    1092                 :            : 
    1093         [ -  + ]:         10 :     if(!m_bRowCountFinal)
    1094         [ #  # ]:          0 :        m_nRowCount = std::max(m_nPosition,m_nRowCount);
    1095                 :            :     OSL_ENSURE(m_nStartPos >= 0,"ORowSetCache::moveWindow: m_nStartPos is less than 0!");
    1096                 :            :     OSL_ENSURE(m_nEndPos > m_nStartPos,"ORowSetCache::moveWindow: m_nStartPos not smaller than m_nEndPos");
    1097                 :            :     OSL_ENSURE(m_nEndPos-m_nStartPos <= m_nFetchSize,"ORowSetCache::moveWindow: m_nStartPos and m_nEndPos too far apart");
    1098                 :            : 
    1099                 :        606 :     return bRet;
    1100                 :            : }
    1101                 :            : 
    1102                 :         50 : sal_Bool ORowSetCache::first(  )
    1103                 :            : {
    1104                 :            :     // First move to the first row.
    1105                 :            :     // Then check if the cache window is at the beginning.
    1106                 :            :     // If not, then position the window and fill it with data.
    1107                 :            :     // We move the window smartly, i.e. we clear only the rows that are out of range
    1108                 :         50 :     sal_Bool bRet = m_pCacheSet->first();
    1109         [ +  + ]:         50 :     if(bRet)
    1110                 :            :     {
    1111                 :         46 :         m_bBeforeFirst  = m_bAfterLast = sal_False;
    1112                 :         46 :         m_nPosition     = 1;
    1113                 :         46 :         moveWindow();
    1114                 :         46 :         m_aMatrixIter   = m_pMatrix->begin();
    1115                 :            :     }
    1116                 :            :     else
    1117                 :            :     {
    1118                 :          4 :         m_bRowCountFinal = m_bBeforeFirst = m_bAfterLast = sal_True;
    1119                 :          4 :         m_nRowCount = m_nPosition = 0;
    1120                 :            : 
    1121                 :            :         OSL_ENSURE(m_bBeforeFirst || m_bNew,"ORowSetCache::first return false and BeforeFirst isn't true");
    1122                 :          4 :         m_aMatrixIter = m_pMatrix->end();
    1123                 :            :     }
    1124                 :         50 :     return bRet;
    1125                 :            : }
    1126                 :            : 
    1127                 :          4 : sal_Bool ORowSetCache::last(  )
    1128                 :            : {
    1129                 :          4 :     sal_Bool bRet = m_pCacheSet->last();
    1130         [ +  - ]:          4 :     if(bRet)
    1131                 :            :     {
    1132                 :          4 :         m_bBeforeFirst = m_bAfterLast = sal_False;
    1133         [ -  + ]:          4 :         if(!m_bRowCountFinal)
    1134                 :            :         {
    1135                 :          0 :             m_bRowCountFinal = sal_True;
    1136                 :          0 :             m_nRowCount = m_pCacheSet->getRow(); // not  + 1
    1137                 :            :         }
    1138                 :          4 :         m_nPosition = m_pCacheSet->getRow();
    1139                 :          4 :         moveWindow();
    1140                 :            :         // we have to repositioning because moveWindow can modify the cache
    1141                 :          4 :         m_pCacheSet->last();
    1142                 :            :         OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!");
    1143                 :          4 :         m_aMatrixIter = calcPosition();
    1144                 :            :     }
    1145                 :            :     else
    1146                 :            :     {
    1147                 :          0 :         m_bRowCountFinal = m_bBeforeFirst = m_bAfterLast = sal_True;
    1148                 :          0 :         m_nRowCount = m_nPosition = 0;
    1149                 :            :         OSL_ENSURE(m_bBeforeFirst,"ORowSetCache::last return false and BeforeFirst isn't true");
    1150                 :          0 :         m_aMatrixIter = m_pMatrix->end();
    1151                 :            :     }
    1152                 :            : #if OSL_DEBUG_LEVEL > 1
    1153                 :            :     if(bRet)
    1154                 :            :     {
    1155                 :            :         OSL_ENSURE((*m_aMatrixIter).is(),"ORowSetCache::last: Row not valid!");
    1156                 :            :     }
    1157                 :            : #endif
    1158                 :            : 
    1159                 :          4 :     return bRet;
    1160                 :            : }
    1161                 :            : 
    1162                 :         62 : sal_Int32 ORowSetCache::getRow(  )
    1163                 :            : {
    1164 [ +  - ][ +  - ]:         62 :     return (isBeforeFirst() || isAfterLast()) ? 0 : m_nPosition;
    1165                 :            : }
    1166                 :            : 
    1167                 :         24 : sal_Bool ORowSetCache::absolute( sal_Int32 row )
    1168                 :            : {
    1169         [ -  + ]:         24 :     if(!row )
    1170 [ #  # ][ #  # ]:          0 :         throw SQLException(DBACORE_RESSTRING(RID_STR_NO_ABS_ZERO),NULL,SQLSTATE_GENERAL,1000,Any() );
         [ #  # ][ #  # ]
    1171                 :            : 
    1172         [ -  + ]:         24 :     if(row < 0)
    1173                 :            :     {
    1174                 :            :         // here we have to scroll from the last row to backward so we have to go to last row and
    1175                 :            :         // and two the previous
    1176 [ #  # ][ #  # ]:          0 :         if(m_bRowCountFinal || last())
                 [ #  # ]
    1177                 :            :         {
    1178                 :          0 :             m_nPosition = m_nRowCount + row + 1; // + row because row is negative and +1 because row==-1 means last row
    1179         [ #  # ]:          0 :             if(m_nPosition < 1)
    1180                 :            :             {
    1181                 :          0 :                 m_bBeforeFirst = sal_True;
    1182                 :          0 :                 m_bAfterLast = sal_False;
    1183                 :          0 :                 m_aMatrixIter = m_pMatrix->end();
    1184                 :            :             }
    1185                 :            :             else
    1186                 :            :             {
    1187                 :          0 :                 m_bBeforeFirst  = sal_False;
    1188                 :          0 :                 m_bAfterLast    = m_nPosition > m_nRowCount;
    1189                 :          0 :                 moveWindow();
    1190                 :            :                 OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!");
    1191                 :          0 :                 m_aMatrixIter = calcPosition();
    1192                 :            :             }
    1193                 :            :         }
    1194                 :            :         else
    1195                 :          0 :             m_aMatrixIter = m_pMatrix->end();
    1196                 :            :     }
    1197                 :            :     else
    1198                 :            :     {
    1199                 :         24 :         m_nPosition = row;
    1200                 :            :         // the position flags
    1201                 :         24 :         m_bBeforeFirst  = sal_False;
    1202                 :         24 :         checkPositionFlags();
    1203                 :            : 
    1204         [ +  - ]:         24 :         if(!m_bAfterLast)
    1205                 :            :         {
    1206                 :         24 :             moveWindow();
    1207                 :         24 :             checkPositionFlags();
    1208         [ +  - ]:         24 :             if(!m_bAfterLast)
    1209                 :         24 :                 m_aMatrixIter = calcPosition();
    1210                 :            :             else
    1211                 :          0 :                 m_aMatrixIter = m_pMatrix->end();
    1212                 :            :         }
    1213                 :            :         else
    1214                 :          0 :             m_aMatrixIter = m_pMatrix->end();
    1215                 :            :     }
    1216                 :            : 
    1217 [ +  - ][ +  - ]:         24 :     return !(m_bAfterLast || m_bBeforeFirst);
    1218                 :            : }
    1219                 :            : 
    1220                 :         16 : sal_Bool ORowSetCache::relative( sal_Int32 rows )
    1221                 :            : {
    1222                 :         16 :     sal_Bool bErg = sal_True;
    1223         [ +  - ]:         16 :     if(rows)
    1224                 :            :     {
    1225                 :         16 :         sal_Int32 nNewPosition = m_nPosition + rows;
    1226                 :            : 
    1227 [ -  + ][ #  # ]:         16 :         if ( m_bBeforeFirst && rows > 0 )
    1228                 :          0 :             nNewPosition = rows;
    1229 [ +  - ][ -  + ]:         16 :         else if ( m_bRowCountFinal && m_bAfterLast && rows < 0 )
                 [ #  # ]
    1230                 :          0 :             nNewPosition = m_nRowCount + 1 + rows;
    1231                 :            :         else
    1232 [ +  - ][ +  - ]:         16 :             if ( m_bBeforeFirst || ( m_bRowCountFinal && m_bAfterLast ) )
                 [ -  + ]
    1233 [ #  # ][ #  # ]:          0 :                 throw SQLException( DBACORE_RESSTRING( RID_STR_NO_RELATIVE ), NULL, SQLSTATE_GENERAL, 1000, Any() );
         [ #  # ][ #  # ]
    1234         [ +  - ]:         16 :         if ( nNewPosition )
    1235                 :            :         {
    1236                 :         16 :             bErg = absolute( nNewPosition );
    1237 [ +  - ][ +  - ]:         16 :             bErg = bErg && !isAfterLast() && !isBeforeFirst();
                 [ +  - ]
    1238                 :            :         }
    1239                 :            :         else
    1240                 :            :         {
    1241                 :          0 :             m_bBeforeFirst = sal_True;
    1242                 :          0 :             bErg = sal_False;
    1243                 :            :         }
    1244                 :            :     }
    1245                 :         16 :     return bErg;
    1246                 :            : }
    1247                 :            : 
    1248                 :          2 : sal_Bool ORowSetCache::previous(  )
    1249                 :            : {
    1250                 :          2 :     sal_Bool bRet = sal_False;
    1251         [ +  - ]:          2 :     if(!isBeforeFirst())
    1252                 :            :     {
    1253         [ -  + ]:          2 :         if(m_bAfterLast)   // we stand after the last row so one before is the last row
    1254                 :          0 :             bRet = last();
    1255                 :            :         else
    1256                 :            :         {
    1257                 :          2 :             m_bAfterLast = sal_False;
    1258                 :          2 :             --m_nPosition;
    1259                 :          2 :             moveWindow();
    1260                 :            :             OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!");
    1261                 :            : 
    1262                 :          2 :             checkPositionFlags();
    1263                 :            : 
    1264         [ -  + ]:          2 :             if(!m_nPosition)
    1265                 :            :             {
    1266                 :          0 :                 m_bBeforeFirst = sal_True;
    1267                 :          0 :                 m_aMatrixIter = m_pMatrix->end();
    1268                 :            :             }
    1269                 :            :             else
    1270                 :            :             {
    1271                 :          2 :                 m_aMatrixIter = calcPosition();
    1272                 :          2 :                 bRet = (*m_aMatrixIter).is();
    1273                 :            :             }
    1274                 :            :         }
    1275                 :            :     }
    1276                 :          2 :     return bRet;
    1277                 :            : }
    1278                 :            : 
    1279                 :          2 : void ORowSetCache::refreshRow(  )
    1280                 :            : {
    1281         [ -  + ]:          2 :     if(isAfterLast())
    1282 [ #  # ][ #  # ]:          0 :         throw SQLException(DBACORE_RESSTRING(RID_STR_NO_REFESH_AFTERLAST),NULL,SQLSTATE_GENERAL,1000,Any() );
         [ #  # ][ #  # ]
    1283                 :            :     OSL_ENSURE(m_aMatrixIter != m_pMatrix->end(),"refreshRow() called for invalid row!");
    1284                 :          2 :     m_pCacheSet->refreshRow();
    1285                 :          2 :     m_pCacheSet->fillValueRow(*m_aMatrixIter,m_nPosition);
    1286         [ -  + ]:          2 :     if ( m_bNew )
    1287                 :            :     {
    1288                 :          0 :         cancelRowModification();
    1289                 :            :     }
    1290                 :          2 : }
    1291                 :            : 
    1292                 :          2 : sal_Bool ORowSetCache::rowUpdated(  )
    1293                 :            : {
    1294                 :          2 :     return m_pCacheSet->rowUpdated();
    1295                 :            : }
    1296                 :            : 
    1297                 :          4 : sal_Bool ORowSetCache::rowInserted(  )
    1298                 :            : {
    1299                 :          4 :     return m_pCacheSet->rowInserted();
    1300                 :            : }
    1301                 :            : 
    1302                 :            : // XResultSetUpdate
    1303                 :          2 : sal_Bool ORowSetCache::insertRow(::std::vector< Any >& o_aBookmarks)
    1304                 :            : {
    1305 [ +  - ][ -  + ]:          2 :     if ( !m_bNew || !m_aInsertRow->is() )
                 [ -  + ]
    1306 [ #  # ][ #  # ]:          0 :         throw SQLException(DBACORE_RESSTRING(RID_STR_NO_MOVETOINSERTROW_CALLED),NULL,SQLSTATE_GENERAL,1000,Any() );
         [ #  # ][ #  # ]
    1307                 :            : 
    1308                 :          2 :     m_pCacheSet->insertRow(*m_aInsertRow,m_aUpdateTable);
    1309                 :            : 
    1310                 :          2 :     sal_Bool bRet( rowInserted() );
    1311         [ +  - ]:          2 :     if ( bRet )
    1312                 :            :     {
    1313                 :          2 :         ++m_nRowCount;
    1314 [ +  - ][ +  - ]:          2 :         Any aBookmark = ((*m_aInsertRow)->get())[0].makeAny();
    1315                 :          2 :         m_bAfterLast = m_bBeforeFirst = sal_False;
    1316         [ +  - ]:          2 :         if(aBookmark.hasValue())
    1317                 :            :         {
    1318         [ +  - ]:          2 :             moveToBookmark(aBookmark);
    1319                 :            :             // update the cached values
    1320                 :          2 :             ORowSetValueVector::Vector& rCurrentRow = ((*m_aMatrixIter))->get();
    1321                 :          2 :             ORowSetMatrix::iterator aIter = m_pMatrix->begin();
    1322 [ +  - ][ +  + ]:        102 :             for(;aIter != m_pMatrix->end();++aIter)
    1323                 :            :             {
    1324 [ +  - ][ +  + ]:        100 :                 if ( m_aMatrixIter != aIter && aIter->is() && m_pCacheSet->columnValuesUpdated((*aIter)->get(),rCurrentRow) )
         [ +  + ][ +  - ]
         [ -  + ][ -  + ]
    1325                 :            :                 {
    1326 [ #  # ][ #  # ]:          0 :                     o_aBookmarks.push_back(lcl_getBookmark((*aIter)->get()[0],m_pCacheSet));
                 [ #  # ]
    1327                 :            :                 }
    1328                 :            :             }
    1329                 :            :         }
    1330                 :            :         else
    1331                 :            :         {
    1332                 :            :             OSL_FAIL("There must be a bookmark after the row was inserted!");
    1333                 :          2 :         }
    1334                 :            :     }
    1335                 :          2 :     return bRet;
    1336                 :            : }
    1337                 :            : 
    1338                 :          2 : void ORowSetCache::resetInsertRow(sal_Bool _bClearInsertRow)
    1339                 :            : {
    1340         [ +  - ]:          2 :     if ( _bClearInsertRow )
    1341                 :          2 :         clearInsertRow();
    1342                 :          2 :     m_bNew      = sal_False;
    1343                 :          2 :     m_bModified = sal_False;
    1344                 :          2 : }
    1345                 :            : 
    1346                 :          0 : void ORowSetCache::cancelRowModification()
    1347                 :            : {
    1348                 :            :     // clear the insertrow references   -> implies that the current row of the rowset changes as well
    1349                 :          0 :     ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin();
    1350                 :          0 :     ORowSetCacheMap::iterator aCacheEnd = m_aCacheIterators.end();
    1351         [ #  # ]:          0 :     for(;aCacheIter != aCacheEnd;++aCacheIter)
    1352                 :            :     {
    1353 [ #  # ][ #  # ]:          0 :         if ( aCacheIter->second.pRowSet->isInsertRow() && aCacheIter->second.aIterator == m_aInsertRow )
         [ #  # ][ #  # ]
    1354                 :          0 :             aCacheIter->second.aIterator = m_pMatrix->end();
    1355                 :            :     }
    1356         [ #  # ]:          0 :     resetInsertRow(sal_False);
    1357                 :          0 : }
    1358                 :            : 
    1359                 :          8 : void ORowSetCache::updateRow( ORowSetMatrix::iterator& _rUpdateRow,::std::vector< Any >& o_aBookmarks )
    1360                 :            : {
    1361 [ +  - ][ -  + ]:          8 :     if(isAfterLast() || isBeforeFirst())
                 [ -  + ]
    1362 [ #  # ][ #  # ]:          0 :         throw SQLException(DBACORE_RESSTRING(RID_STR_NO_UPDATEROW),NULL,SQLSTATE_GENERAL,1000,Any() );
         [ #  # ][ #  # ]
    1363                 :            : 
    1364 [ +  - ][ +  - ]:          8 :     Any aBookmark = ((*_rUpdateRow)->get())[0].makeAny();
    1365                 :            :     OSL_ENSURE(aBookmark.hasValue(),"Bookmark must have a value!");
    1366                 :            :     // here we don't have to reposition our CacheSet, when we try to update a row,
    1367                 :            :     // the row was already fetched
    1368         [ +  - ]:          8 :     moveToBookmark(aBookmark);
    1369         [ +  - ]:          8 :     m_pCacheSet->updateRow(*_rUpdateRow,*m_aMatrixIter,m_aUpdateTable);
    1370                 :            :     // refetch the whole row
    1371         [ +  - ]:          8 :     (*m_aMatrixIter) = NULL;
    1372                 :            : 
    1373 [ +  - ][ +  - ]:          8 :     if ( moveToBookmark(aBookmark) )
    1374                 :            :     {
    1375                 :            :         // update the cached values
    1376                 :          8 :         ORowSetValueVector::Vector& rCurrentRow = ((*m_aMatrixIter))->get();
    1377                 :          8 :         ORowSetMatrix::iterator aIter = m_pMatrix->begin();
    1378 [ +  - ][ +  + ]:        408 :         for(;aIter != m_pMatrix->end();++aIter)
    1379                 :            :         {
    1380 [ +  - ][ +  + ]:        400 :             if ( m_aMatrixIter != aIter && aIter->is() && m_pCacheSet->columnValuesUpdated((*aIter)->get(),rCurrentRow) )
         [ +  + ][ +  - ]
         [ -  + ][ -  + ]
    1381                 :            :             {
    1382 [ #  # ][ #  # ]:          0 :                 o_aBookmarks.push_back(lcl_getBookmark((*aIter)->get()[0],m_pCacheSet));
                 [ #  # ]
    1383                 :            :             }
    1384                 :            :         }
    1385                 :            :     }
    1386                 :            : 
    1387                 :          8 :     m_bModified = sal_False;
    1388                 :          8 : }
    1389                 :            : 
    1390                 :          2 : bool ORowSetCache::deleteRow(  )
    1391                 :            : {
    1392 [ +  - ][ -  + ]:          2 :     if(isAfterLast() || isBeforeFirst())
                 [ -  + ]
    1393 [ #  # ][ #  # ]:          0 :         throw SQLException(DBACORE_RESSTRING(RID_STR_NO_DELETEROW),NULL,SQLSTATE_GENERAL,1000,Any() );
         [ #  # ][ #  # ]
    1394                 :            : 
    1395         [ +  - ]:          2 :     m_pCacheSet->deleteRow(*m_aMatrixIter,m_aUpdateTable);
    1396 [ +  - ][ -  + ]:          2 :     if ( !m_pCacheSet->rowDeleted() )
    1397                 :          0 :         return false;
    1398                 :            : 
    1399                 :          2 :     --m_nRowCount;
    1400                 :            :     OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!");
    1401         [ +  - ]:          2 :     ORowSetMatrix::iterator aPos = calcPosition();
    1402         [ +  - ]:          2 :     (*aPos)   = NULL;
    1403                 :            : 
    1404                 :          2 :     ORowSetMatrix::iterator aEnd = m_pMatrix->end();
    1405 [ +  - ][ +  - ]:          2 :     for(++aPos;aPos != aEnd && aPos->is();++aPos)
         [ -  + ][ -  + ]
    1406                 :            :     {
    1407 [ #  # ][ #  # ]:          0 :         *(aPos-1) = *aPos;
    1408         [ #  # ]:          0 :         (*aPos)   = NULL;
    1409                 :            :     }
    1410                 :          2 :     m_aMatrixIter = m_pMatrix->end();
    1411                 :            : 
    1412                 :          2 :     --m_nPosition;
    1413                 :          2 :     return true;
    1414                 :            : }
    1415                 :            : 
    1416                 :          2 : void ORowSetCache::cancelRowUpdates(  )
    1417                 :            : {
    1418                 :          2 :     m_bNew = m_bModified = sal_False;
    1419         [ -  + ]:          2 :     if(!m_nPosition)
    1420                 :            :     {
    1421                 :            :         OSL_FAIL("cancelRowUpdates:Invalid positions pos == 0");
    1422 [ #  # ][ #  # ]:          0 :         ::dbtools::throwFunctionSequenceException(NULL);
    1423                 :            :     }
    1424                 :            : 
    1425         [ +  - ]:          2 :     if(m_pCacheSet->absolute(m_nPosition))
    1426                 :          2 :         m_pCacheSet->fillValueRow(*m_aMatrixIter,m_nPosition);
    1427                 :            :     else
    1428                 :            :     {
    1429                 :            :         OSL_FAIL("cancelRowUpdates couldn't position right with absolute");
    1430 [ #  # ][ #  # ]:          0 :         ::dbtools::throwFunctionSequenceException(NULL);
    1431                 :            :     }
    1432                 :          2 : }
    1433                 :            : 
    1434                 :          2 : void ORowSetCache::moveToInsertRow(  )
    1435                 :            : {
    1436                 :          2 :     m_bNew      = sal_True;
    1437                 :          2 :     m_bUpdated  = m_bAfterLast = sal_False;
    1438                 :            : 
    1439                 :          2 :     m_aInsertRow = m_pInsertMatrix->begin();
    1440         [ +  - ]:          2 :     if(!m_aInsertRow->is())
    1441 [ +  - ][ +  - ]:          2 :         *m_aInsertRow = new ORowSetValueVector(m_xMetaData->getColumnCount());
         [ +  - ][ +  - ]
    1442                 :            : 
    1443                 :            :     // we don't unbound the bookmark column
    1444         [ +  - ]:          2 :     ORowSetValueVector::Vector::iterator aIter = (*m_aInsertRow)->get().begin()+1;
    1445                 :          2 :     ORowSetValueVector::Vector::iterator aEnd = (*m_aInsertRow)->get().end();
    1446 [ +  - ][ +  - ]:         64 :     for(sal_Int32 i = 1;aIter != aEnd;++aIter,++i)
                 [ +  + ]
    1447                 :            :     {
    1448         [ +  - ]:         62 :         aIter->setBound(sal_False);
    1449         [ +  - ]:         62 :         aIter->setModified(sal_False);
    1450 [ +  - ][ +  - ]:         62 :         aIter->setNull();
    1451 [ +  - ][ +  - ]:         62 :         aIter->setTypeKind(m_xMetaData->getColumnType(i));
         [ +  - ][ +  - ]
    1452                 :            :     }
    1453                 :          2 : }
    1454                 :            : 
    1455                 :         44 : ORowSetCacheIterator ORowSetCache::createIterator(ORowSetBase* _pRowSet)
    1456                 :            : {
    1457                 :         44 :     ORowSetCacheIterator_Helper aHelper;
    1458                 :         44 :     aHelper.aIterator = m_pMatrix->end();
    1459                 :         44 :     aHelper.pRowSet = _pRowSet;
    1460         [ +  - ]:         44 :     return ORowSetCacheIterator(m_aCacheIterators.insert(m_aCacheIterators.begin(),ORowSetCacheMap::value_type(m_aCacheIterators.size()+1,aHelper)),this,_pRowSet);
    1461                 :            : }
    1462                 :            : 
    1463                 :          4 : void ORowSetCache::deleteIterator(const ORowSetBase* _pRowSet)
    1464                 :            : {
    1465                 :          4 :     ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin();
    1466         [ +  + ]:         16 :     for(;aCacheIter != m_aCacheIterators.end();)
    1467                 :            :     {
    1468         [ +  + ]:         12 :         if ( aCacheIter->second.pRowSet == _pRowSet )
    1469                 :            :         {
    1470         [ +  - ]:          4 :             m_aCacheIterators.erase(aCacheIter);
    1471                 :          4 :             aCacheIter = m_aCacheIterators.begin();
    1472                 :            :         }
    1473                 :            :         else
    1474                 :          8 :             ++aCacheIter;
    1475                 :            :     }
    1476                 :          4 : }
    1477                 :            : 
    1478                 :         10 : void ORowSetCache::rotateCacheIterator(ORowSetMatrix::difference_type _nDist)
    1479                 :            : {
    1480         [ -  + ]:         10 :     if(_nDist)
    1481                 :            :     {
    1482                 :            :         // now correct the iterator in our iterator vector
    1483                 :          0 :         ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin();
    1484                 :          0 :         ORowSetCacheMap::iterator aCacheEnd  = m_aCacheIterators.end();
    1485         [ #  # ]:          0 :         for(;aCacheIter != aCacheEnd;++aCacheIter)
    1486                 :            :         {
    1487 [ #  # ][ #  # ]:          0 :             if ( !aCacheIter->second.pRowSet->isInsertRow()
         [ #  # ][ #  # ]
    1488 [ #  # ][ #  # ]:          0 :                 && aCacheIter->second.aIterator != m_pMatrix->end() && !m_bModified )
                 [ #  # ]
    1489                 :            :             {
    1490         [ #  # ]:          0 :                 ptrdiff_t nDist = (aCacheIter->second.aIterator - m_pMatrix->begin());
    1491         [ #  # ]:          0 :                 if(nDist < _nDist)
    1492                 :            :                 {
    1493                 :          0 :                     aCacheIter->second.aIterator = m_pMatrix->end();
    1494                 :            :                 }
    1495                 :            :                 else
    1496                 :            :                 {
    1497                 :            :                     OSL_ENSURE((aCacheIter->second.aIterator - m_pMatrix->begin()) >= _nDist,"Invalid Dist value!");
    1498                 :          0 :                     aCacheIter->second.aIterator -= _nDist;
    1499                 :            :                     OSL_ENSURE(aCacheIter->second.aIterator >= m_pMatrix->begin()
    1500                 :            :                             && aCacheIter->second.aIterator < m_pMatrix->end(),"Iterator out of area!");
    1501                 :            :                 }
    1502                 :            :             }
    1503                 :            :         }
    1504                 :            :     }
    1505                 :         10 : }
    1506                 :            : 
    1507                 :         10 : void ORowSetCache::setUpdateIterator(const ORowSetMatrix::iterator& _rOriginalRow)
    1508                 :            : {
    1509                 :         10 :     m_aInsertRow = m_pInsertMatrix->begin();
    1510         [ +  - ]:         10 :     if(!m_aInsertRow->is())
    1511 [ +  - ][ +  - ]:         10 :         *m_aInsertRow = new ORowSetValueVector(m_xMetaData->getColumnCount());
         [ +  - ][ +  - ]
    1512                 :            : 
    1513         [ +  - ]:         10 :     (*(*m_aInsertRow)) = (*(*_rOriginalRow));
    1514                 :            :     // we don't unbound the bookmark column
    1515                 :         10 :     ORowSetValueVector::Vector::iterator aIter = (*m_aInsertRow)->get().begin();
    1516                 :         10 :     ORowSetValueVector::Vector::iterator aEnd = (*m_aInsertRow)->get().end();
    1517 [ +  - ][ +  + ]:         90 :     for(;aIter != aEnd;++aIter)
                 [ +  - ]
    1518         [ +  - ]:         80 :         aIter->setModified(sal_False);
    1519                 :         10 : }
    1520                 :            : 
    1521                 :       1102 : void ORowSetCache::checkPositionFlags()
    1522                 :            : {
    1523         [ +  - ]:       1102 :     if(m_bRowCountFinal)
    1524                 :            :     {
    1525                 :       1102 :         m_bAfterLast    = m_nPosition > m_nRowCount;
    1526         [ +  + ]:       1102 :         if(m_bAfterLast)
    1527                 :          8 :             m_nPosition = 0;//m_nRowCount;
    1528                 :            :     }
    1529                 :       1102 : }
    1530                 :            : 
    1531                 :         12 : void ORowSetCache::checkUpdateConditions(sal_Int32 columnIndex)
    1532                 :            : {
    1533 [ +  - ][ -  + ]:         12 :     if(m_bAfterLast || columnIndex >= (sal_Int32)(*m_aInsertRow)->get().size())
                 [ -  + ]
    1534 [ #  # ][ #  # ]:          0 :         throwFunctionSequenceException(m_xSet.get());
    1535                 :         12 : }
    1536                 :            : 
    1537                 :          0 : sal_Bool ORowSetCache::checkInnerJoin(const ::connectivity::OSQLParseNode *pNode,const Reference< XConnection>& _xConnection,const ::rtl::OUString& _sUpdateTableName)
    1538                 :            : {
    1539                 :          0 :     sal_Bool bOk = sal_False;
    1540   [ #  #  #  #  :          0 :     if (pNode->count() == 3 &&  // Ausdruck is geklammert
          #  #  #  #  #  
              # ][ #  # ]
    1541                 :          0 :         SQL_ISPUNCTUATION(pNode->getChild(0),"(") &&
    1542                 :          0 :         SQL_ISPUNCTUATION(pNode->getChild(2),")"))
    1543                 :            :     {
    1544                 :          0 :         bOk = checkInnerJoin(pNode->getChild(1),_xConnection,_sUpdateTableName);
    1545                 :            :     }
    1546 [ #  # ][ #  # ]:          0 :     else if ((SQL_ISRULE(pNode,search_condition) || SQL_ISRULE(pNode,boolean_term)) && // AND/OR link
                 [ #  # ]
           [ #  #  #  # ]
                 [ #  # ]
    1547                 :          0 :                 pNode->count() == 3)
    1548                 :            :     {
    1549                 :            :         // only allow an AND link
    1550 [ #  # ][ #  # ]:          0 :         if ( SQL_ISTOKEN(pNode->getChild(1),AND) )
                 [ #  # ]
    1551                 :          0 :             bOk = checkInnerJoin(pNode->getChild(0),_xConnection,_sUpdateTableName)
    1552 [ #  # ][ #  # ]:          0 :                 && checkInnerJoin(pNode->getChild(2),_xConnection,_sUpdateTableName);
    1553                 :            :     }
    1554 [ #  # ][ #  # ]:          0 :     else if (SQL_ISRULE(pNode,comparison_predicate))
                 [ #  # ]
    1555                 :            :     {
    1556                 :            :         // only the comparison of columns is allowed
    1557                 :            :         OSL_ENSURE(pNode->count() == 3,"checkInnerJoin: Fehler im Parse Tree");
    1558 [ #  # ][ #  # ]:          0 :         if (!(SQL_ISRULE(pNode->getChild(0),column_ref) &&
         [ #  # ][ #  # ]
    1559 [ #  # ][ #  # ]:          0 :                 SQL_ISRULE(pNode->getChild(2),column_ref) &&
                 [ #  # ]
    1560   [ #  #  #  # ]:          0 :                 pNode->getChild(1)->getNodeType() == SQL_NODE_EQUAL))
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1561                 :            :         {
    1562                 :          0 :             bOk = sal_False;
    1563                 :            :         }
    1564                 :          0 :         ::rtl::OUString sColumnName,sTableRange;
    1565 [ #  # ][ #  # ]:          0 :         OSQLParseTreeIterator::getColumnRange( pNode->getChild(0), _xConnection, sColumnName, sTableRange );
    1566                 :          0 :         bOk = sTableRange == _sUpdateTableName;
    1567         [ #  # ]:          0 :         if ( !bOk )
    1568                 :            :         {
    1569 [ #  # ][ #  # ]:          0 :             OSQLParseTreeIterator::getColumnRange( pNode->getChild(2), _xConnection, sColumnName, sTableRange );
    1570                 :          0 :             bOk =  sTableRange == _sUpdateTableName;
    1571                 :          0 :         }
    1572                 :            :     }
    1573                 :          0 :     return bOk;
    1574                 :            : }
    1575                 :            : 
    1576                 :          0 : sal_Bool ORowSetCache::checkJoin(const Reference< XConnection>& _xConnection,
    1577                 :            :                                  const Reference< XSingleSelectQueryAnalyzer >& _xAnalyzer,
    1578                 :            :                                  const ::rtl::OUString& _sUpdateTableName )
    1579                 :            : {
    1580                 :          0 :     sal_Bool bOk = sal_False;
    1581 [ #  # ][ #  # ]:          0 :     ::rtl::OUString sSql = _xAnalyzer->getQuery();
    1582                 :          0 :     ::rtl::OUString sErrorMsg;
    1583 [ #  # ][ #  # ]:          0 :     ::connectivity::OSQLParser aSqlParser( m_aContext.getLegacyServiceFactory() );
    1584                 :            :     SAL_WNODEPRECATED_DECLARATIONS_PUSH
    1585         [ #  # ]:          0 :     ::std::auto_ptr< ::connectivity::OSQLParseNode> pSqlParseNode( aSqlParser.parseTree(sErrorMsg,sSql));
    1586                 :            :     SAL_WNODEPRECATED_DECLARATIONS_POP
    1587 [ #  # ][ #  # ]:          0 :     if ( pSqlParseNode.get() && SQL_ISRULE(pSqlParseNode, select_statement) )
         [ #  # ][ #  # ]
                 [ #  # ]
    1588                 :            :     {
    1589         [ #  # ]:          0 :         OSQLParseNode* pTableRefCommalist = pSqlParseNode->getByRule(::connectivity::OSQLParseNode::table_ref_commalist);
    1590                 :            :         OSL_ENSURE(pTableRefCommalist,"NO tables why!?");
    1591 [ #  # ][ #  # ]:          0 :         if(pTableRefCommalist && pTableRefCommalist->count() == 1)
                 [ #  # ]
    1592                 :            :         {
    1593                 :            :             // we found only one element so it must some kind of join here
    1594         [ #  # ]:          0 :             OSQLParseNode* pJoin = pTableRefCommalist->getByRule(::connectivity::OSQLParseNode::qualified_join);
    1595         [ #  # ]:          0 :             if(pJoin)
    1596                 :            :             { // we are only intereseted in qualified joins like RIGHT or LEFT
    1597         [ #  # ]:          0 :                 OSQLParseNode* pJoinType    = pJoin->getChild(1);
    1598                 :          0 :                 OSQLParseNode* pOuterType   = NULL;
    1599 [ #  # ][ #  # ]:          0 :                 if(SQL_ISRULE(pJoinType,join_type) && pJoinType->count() == 2)
         [ #  # ][ #  # ]
                 [ #  # ]
    1600         [ #  # ]:          0 :                     pOuterType = pJoinType->getChild(0);
    1601 [ #  # ][ #  # ]:          0 :                 else if(SQL_ISRULE(pJoinType,outer_join_type))
         [ #  # ][ #  # ]
    1602                 :          0 :                     pOuterType = pJoinType;
    1603                 :            : 
    1604                 :          0 :                 sal_Bool bCheck     = sal_False;
    1605                 :          0 :                 sal_Bool bLeftSide  = sal_False;
    1606         [ #  # ]:          0 :                 if(pOuterType)
    1607                 :            :                 { // found outer join
    1608 [ #  # ][ #  # ]:          0 :                     bLeftSide = SQL_ISTOKEN(pOuterType->getChild(0),LEFT);
         [ #  # ][ #  # ]
    1609 [ #  # ][ #  # ]:          0 :                     bCheck = bLeftSide || SQL_ISTOKEN(pOuterType->getChild(0),RIGHT);
         [ #  # ][ #  # ]
                 [ #  # ]
    1610                 :            :                 }
    1611                 :            : 
    1612         [ #  # ]:          0 :                 if(bCheck)
    1613                 :            :                 { // here we know that we have to check on which side our table resides
    1614         [ #  # ]:          0 :                     const OSQLParseNode* pTableRef = pJoin->getByRule(::connectivity::OSQLParseNode::qualified_join);
    1615         [ #  # ]:          0 :                     if(bLeftSide)
    1616         [ #  # ]:          0 :                         pTableRef = pJoin->getChild(0);
    1617                 :            :                     else
    1618         [ #  # ]:          0 :                         pTableRef = pJoin->getChild(3);
    1619                 :            :                     OSL_ENSURE(SQL_ISRULE(pTableRef,table_ref),"Must be a tableref here!");
    1620                 :            : 
    1621         [ #  # ]:          0 :                     ::rtl::OUString sTableRange = OSQLParseNode::getTableRange(pTableRef);
    1622         [ #  # ]:          0 :                     if(sTableRange.isEmpty())
    1623 [ #  # ][ #  # ]:          0 :                         pTableRef->getChild(0)->parseNodeToStr( sTableRange, _xConnection, NULL, sal_False, sal_False );
    1624                 :          0 :                     bOk =  sTableRange == _sUpdateTableName;
    1625                 :            :                 }
    1626                 :            :             }
    1627                 :            :         }
    1628                 :            :         else
    1629                 :            :         {
    1630 [ #  # ][ #  # ]:          0 :             OSQLParseNode* pWhereOpt = pSqlParseNode->getChild(3)->getChild(1);
    1631 [ #  # ][ #  # ]:          0 :             if ( pWhereOpt && !pWhereOpt->isLeaf() )
                 [ #  # ]
    1632 [ #  # ][ #  # ]:          0 :                 bOk = checkInnerJoin(pWhereOpt->getChild(1),_xConnection,_sUpdateTableName);
    1633                 :            :         }
    1634                 :            :     }
    1635 [ #  # ][ #  # ]:          0 :     return bOk;
    1636                 :            : }
    1637                 :            : 
    1638                 :          2 : void ORowSetCache::clearInsertRow()
    1639                 :            : {
    1640                 :            :     // we don't unbound the bookmark column
    1641 [ +  - ][ +  - ]:          2 :     if ( m_aInsertRow != m_pInsertMatrix->end() && m_aInsertRow->is() )
         [ +  - ][ +  - ]
           [ +  -  #  # ]
    1642                 :            :     {
    1643         [ +  - ]:          2 :         ORowSetValueVector::Vector::iterator aIter = (*m_aInsertRow)->get().begin()+1;
    1644                 :          2 :         ORowSetValueVector::Vector::iterator aEnd = (*m_aInsertRow)->get().end();
    1645 [ +  - ][ +  - ]:         64 :         for(;aIter != aEnd;++aIter)
                 [ +  + ]
    1646                 :            :         {
    1647         [ +  - ]:         62 :             aIter->setBound(sal_False);
    1648         [ +  - ]:         62 :             aIter->setModified(sal_False);
    1649 [ +  - ][ +  - ]:         62 :             aIter->setNull();
    1650                 :            :         }
    1651                 :            :     }
    1652                 :          2 : }
    1653                 :            : 
    1654                 :       1156 : ORowSetMatrix::iterator ORowSetCache::calcPosition() const
    1655                 :            : {
    1656                 :       1156 :     sal_Int32 nValue = (m_nPosition - m_nStartPos) - 1;
    1657                 :            :     CHECK_MATRIX_POS(nValue);
    1658 [ +  - ][ -  + ]:       1156 :     return ( nValue < 0 || nValue >= static_cast<sal_Int32>(m_pMatrix->size()) ) ? m_pMatrix->end() : (m_pMatrix->begin() + nValue);
         [ +  - ][ +  - ]
                 [ +  - ]
           [ #  #  #  # ]
    1659                 :            : }
    1660                 :            : 
    1661                 :         44 : TORowSetOldRowHelperRef ORowSetCache::registerOldRow()
    1662                 :            : {
    1663 [ +  - ][ +  - ]:         44 :     TORowSetOldRowHelperRef pRef = new ORowSetOldRowHelper(ORowSetRow());
         [ +  - ][ +  - ]
    1664         [ +  - ]:         44 :     m_aOldRows.push_back(pRef);
    1665                 :         44 :     return pRef;
    1666                 :            : }
    1667                 :            : 
    1668                 :          4 : void ORowSetCache::deregisterOldRow(const TORowSetOldRowHelperRef& _rRow)
    1669                 :            : {
    1670                 :          4 :     TOldRowSetRows::iterator aOldRowEnd = m_aOldRows.end();
    1671 [ +  - ][ +  - ]:          8 :     for (TOldRowSetRows::iterator aOldRowIter = m_aOldRows.begin(); aOldRowIter != aOldRowEnd; ++aOldRowIter)
    1672                 :            :     {
    1673         [ +  + ]:          8 :         if ( aOldRowIter->get() == _rRow.get() )
    1674                 :            :         {
    1675         [ +  - ]:          4 :             m_aOldRows.erase(aOldRowIter);
    1676                 :          4 :             break;
    1677                 :            :         }
    1678                 :            : 
    1679                 :            :     }
    1680                 :          4 : }
    1681                 :            : 
    1682                 :          0 : sal_Bool ORowSetCache::reFillMatrix(sal_Int32 _nNewStartPos,sal_Int32 _nNewEndPos)
    1683                 :            : {
    1684                 :            :     OSL_ENSURE( _nNewEndPos - _nNewStartPos == m_nFetchSize, "reFillMatrix called with Start/EndPos not m_nFetchSize apart");
    1685         [ #  # ]:          0 :     const TOldRowSetRows::const_iterator aOldRowEnd = m_aOldRows.end();
    1686 [ #  # ][ #  # ]:          0 :     for (TOldRowSetRows::iterator aOldRowIter = m_aOldRows.begin(); aOldRowIter != aOldRowEnd; ++aOldRowIter)
    1687                 :            :     {
    1688 [ #  # ][ #  # ]:          0 :         if ( aOldRowIter->is() && (*aOldRowIter)->getRow().is() )
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    1689 [ #  # ][ #  # ]:          0 :             (*aOldRowIter)->setRow(new ORowSetValueVector( *((*aOldRowIter)->getRow()) ) );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1690                 :            :     }
    1691                 :          0 :     sal_Int32 nNewSt = _nNewStartPos;
    1692         [ #  # ]:          0 :     sal_Bool bRet = fillMatrix(nNewSt,_nNewEndPos);
    1693                 :          0 :     m_nStartPos = nNewSt;
    1694                 :          0 :     m_nEndPos = _nNewEndPos;
    1695         [ #  # ]:          0 :     rotateCacheIterator(static_cast<ORowSetMatrix::difference_type>(m_nFetchSize+1)); // invalidate every iterator
    1696                 :          0 :     return bRet;
    1697                 :            : }
    1698                 :            : 
    1699                 :         20 : sal_Bool ORowSetCache::fill(ORowSetMatrix::iterator& _aIter,const ORowSetMatrix::const_iterator& _aEnd,sal_Int32& _nPos,sal_Bool _bCheck)
    1700                 :            : {
    1701                 :         20 :     const sal_Int32 nColumnCount = m_xMetaData->getColumnCount();
    1702 [ +  + ][ +  - ]:         22 :     for(; _bCheck && _aIter != _aEnd; _aIter++, _nPos++)
                 [ +  + ]
    1703                 :            :     {
    1704         [ +  - ]:          2 :         if ( !_aIter->is() )
    1705         [ +  - ]:          2 :             *_aIter = new ORowSetValueVector(nColumnCount);
    1706                 :            :         else
    1707                 :            :         {
    1708         [ #  # ]:          0 :             const TOldRowSetRows::const_iterator aOldRowEnd = m_aOldRows.end();
    1709 [ #  # ][ #  # ]:          0 :             for (TOldRowSetRows::iterator aOldRowIter = m_aOldRows.begin(); aOldRowIter != aOldRowEnd; ++aOldRowIter)
    1710                 :            :             {
    1711 [ #  # ][ #  # ]:          0 :                 if ( (*aOldRowIter)->getRow() == *_aIter )
                 [ #  # ]
    1712 [ #  # ][ #  # ]:          0 :                     *_aIter = new ORowSetValueVector(nColumnCount);
    1713                 :            :             }
    1714                 :            :         }
    1715                 :          2 :         m_pCacheSet->fillValueRow(*_aIter, _nPos);
    1716                 :          2 :         _bCheck = m_pCacheSet->next();
    1717                 :            :     }
    1718                 :         20 :     return _bCheck;
    1719                 :            : }
    1720                 :            : 
    1721                 :          8 : bool ORowSetCache::isResultSetChanged() const
    1722                 :            : {
    1723                 :          8 :     return m_pCacheSet->isResultSetChanged();
    1724                 :            : }
    1725                 :            : 
    1726                 :          0 : void ORowSetCache::reset(const Reference< XResultSet>& _xDriverSet)
    1727                 :            : {
    1728 [ #  # ][ #  # ]:          0 :     m_xMetaData.set(Reference< XResultSetMetaDataSupplier >(_xDriverSet,UNO_QUERY)->getMetaData());
                 [ #  # ]
    1729                 :          0 :     m_pCacheSet->reset(_xDriverSet);
    1730                 :            : 
    1731                 :          0 :     m_bRowCountFinal = sal_False;
    1732                 :          0 :     m_nRowCount = 0;
    1733                 :          0 :     reFillMatrix(m_nStartPos,m_nEndPos);
    1734                 :          0 : }
    1735                 :            : 
    1736                 :         12 : void ORowSetCache::impl_updateRowFromCache_throw(ORowSetValueVector::Vector& io_aRow
    1737                 :            :                                            ,::std::vector<sal_Int32>& o_ChangedColumns)
    1738                 :            : {
    1739         [ -  + ]:         12 :     if ( o_ChangedColumns.size() > 1 )
    1740                 :            :     {
    1741                 :          0 :         ORowSetMatrix::iterator aIter = m_pMatrix->begin();
    1742 [ #  # ][ #  # ]:          0 :         for(;aIter != m_pMatrix->end();++aIter)
    1743                 :            :         {
    1744 [ #  # ][ #  # ]:          0 :             if ( aIter->is() && m_pCacheSet->updateColumnValues((*aIter)->get(),io_aRow,o_ChangedColumns))
         [ #  # ][ #  # ]
    1745                 :            :             {
    1746                 :          0 :                 break;
    1747                 :            :             }
    1748                 :            :         }
    1749                 :            : 
    1750 [ #  # ][ #  # ]:          0 :         if ( aIter == m_pMatrix->end() )
    1751                 :            :         {
    1752         [ #  # ]:          0 :             m_pCacheSet->fillMissingValues(io_aRow);
    1753                 :            :         }
    1754                 :            :     }
    1755                 :         12 : }
    1756                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10