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