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