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