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