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 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 467 Reference< XResultSetMetaData > ORowSetCache::getMetaData( ) 468 { 469 return m_xMetaData; 470 } 471 // ------------------------------------------------------------------------- 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 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 552 sal_Bool ORowSetCache::hasOrderedBookmarks( ) 553 { 554 return m_pCacheSet->hasOrderedBookmarks(); 555 } 556 // ------------------------------------------------------------------------- 557 sal_Int32 ORowSetCache::hashBookmark( const Any& bookmark ) 558 { 559 return m_pCacheSet->hashBookmark(bookmark); 560 } 561 // XRowUpdate 562 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 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 // ------------------------------------------------------------------------- 690 sal_Bool ORowSetCache::isBeforeFirst( ) 691 { 692 return m_bBeforeFirst; 693 } 694 // ------------------------------------------------------------------------- 695 sal_Bool ORowSetCache::isAfterLast( ) 696 { 697 return m_bAfterLast; 698 } 699 // ------------------------------------------------------------------------- 700 sal_Bool ORowSetCache::isFirst( ) 701 { 702 return m_nPosition == 1; // ask resultset for 703 } 704 // ------------------------------------------------------------------------- 705 sal_Bool ORowSetCache::isLast( ) 706 { 707 return m_nPosition == m_nRowCount; 708 } 709 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 beginning 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 // ------------------------------------------------------------------------- 1063 sal_Bool ORowSetCache::first( ) 1064 { 1065 // first move to the first row 1066 // then check if the cache window is at the beginning 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 1127 sal_Int32 ORowSetCache::getRow( ) 1128 { 1129 return (isBeforeFirst() || isAfterLast()) ? 0 : m_nPosition; 1130 } 1131 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 1257 sal_Bool ORowSetCache::rowUpdated( ) 1258 { 1259 return m_pCacheSet->rowUpdated(); 1260 } 1261 // ------------------------------------------------------------------------- 1262 sal_Bool ORowSetCache::rowInserted( ) 1263 { 1264 return m_pCacheSet->rowInserted(); 1265 } 1266 // ------------------------------------------------------------------------- 1267 // XResultSetUpdate 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 //------------------------------------------------------------------------------ 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 1619 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 1627 TORowSetOldRowHelperRef ORowSetCache::registerOldRow() 1628 { 1629 TORowSetOldRowHelperRef pRef = new ORowSetOldRowHelper(ORowSetRow()); 1630 m_aOldRows.push_back(pRef); 1631 return pRef; 1632 } 1633 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 1685 bool ORowSetCache::isResultSetChanged() const 1686 { 1687 return m_pCacheSet->isResultSetChanged(); 1688 } 1689 // ----------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------------- 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