Bump version to 5.0-14
[LibreOffice.git] / dbaccess / source / core / api / RowSetBase.cxx
blob547c2c113090153f20bceba0b71ff7760d008e78
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "RowSetBase.hxx"
21 #include "CRowSetDataColumn.hxx"
22 #include <connectivity/sdbcx/VCollection.hxx>
23 #include "RowSetCache.hxx"
24 #include "dbastrings.hrc"
25 #include "core_resource.hrc"
26 #include <com/sun/star/lang/DisposedException.hpp>
27 #include <com/sun/star/beans/PropertyAttribute.hpp>
28 #include <com/sun/star/sdbcx/CompareBookmark.hpp>
29 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
30 #include <com/sun/star/lang/Locale.hpp>
31 #include <com/sun/star/util/NumberFormat.hpp>
32 #include <comphelper/sequence.hxx>
33 #include <comphelper/seqstream.hxx>
34 #include <connectivity/dbexception.hxx>
35 #include <tools/debug.hxx>
37 using namespace dbaccess;
38 using namespace connectivity;
39 using namespace connectivity::sdbcx;
40 using namespace comphelper;
41 using namespace dbtools;
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star::beans;
44 using namespace ::com::sun::star::sdbc;
45 using namespace ::com::sun::star::sdb;
46 using namespace ::com::sun::star::sdbcx;
47 using namespace ::com::sun::star::container;
48 using namespace ::com::sun::star::lang;
49 using namespace ::com::sun::star::util;
50 using namespace ::cppu;
51 using namespace ::osl;
53 namespace dbaccess
56 // OEmptyCollection
57 class OEmptyCollection : public sdbcx::OCollection
59 protected:
60 virtual void impl_refresh() throw(RuntimeException) SAL_OVERRIDE;
61 virtual connectivity::sdbcx::ObjectType createObject(const OUString& _rName) SAL_OVERRIDE;
62 public:
63 OEmptyCollection(::cppu::OWeakObject& _rParent,::osl::Mutex& _rMutex) : OCollection(_rParent, true, _rMutex, ::std::vector< OUString>()){}
66 void OEmptyCollection::impl_refresh() throw(RuntimeException)
70 connectivity::sdbcx::ObjectType OEmptyCollection::createObject(const OUString& /*_rName*/)
72 return connectivity::sdbcx::ObjectType();
75 // ORowSetBase
77 ORowSetBase::ORowSetBase( const Reference<XComponentContext>& _rContext, ::cppu::OBroadcastHelper& _rBHelper, ::osl::Mutex* _pMutex )
78 :OPropertyStateContainer(_rBHelper)
79 ,m_pMutex(_pMutex)
80 ,m_pMySelf(NULL)
81 ,m_pCache(NULL)
82 ,m_pColumns(NULL)
83 ,m_rBHelper(_rBHelper)
84 ,m_pEmptyCollection( NULL )
85 ,m_aContext( _rContext )
86 ,m_aErrors( _rContext )
87 ,m_nLastColumnIndex(-1)
88 ,m_nDeletedPosition(-1)
89 ,m_nResultSetType( ResultSetType::FORWARD_ONLY )
90 ,m_nResultSetConcurrency( ResultSetConcurrency::READ_ONLY )
91 ,m_bClone(false)
92 ,m_bIgnoreResult(false)
93 ,m_bBeforeFirst(true) // changed from sal_False
94 ,m_bAfterLast(false)
95 ,m_bIsInsertRow(false)
97 sal_Int32 nRBT = PropertyAttribute::READONLY | PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT;
99 sal_Int32 nInitialRowCountValue = 0;
100 sal_Bool bInitialRowCountFinalValue( sal_False );
101 registerPropertyNoMember( PROPERTY_ROWCOUNT, PROPERTY_ID_ROWCOUNT, nRBT, cppu::UnoType<decltype(nInitialRowCountValue)>::get(), &nInitialRowCountValue );
102 registerPropertyNoMember( PROPERTY_ISROWCOUNTFINAL, PROPERTY_ID_ISROWCOUNTFINAL, nRBT, cppu::UnoType<bool>::get(), &bInitialRowCountFinalValue );
105 ORowSetBase::~ORowSetBase()
107 if(m_pColumns)
109 TDataColumns().swap(m_aDataColumns);
110 m_pColumns->acquire();
111 m_pColumns->disposing();
112 delete m_pColumns;
113 m_pColumns = NULL;
116 if ( m_pEmptyCollection )
117 delete m_pEmptyCollection;
121 // com::sun::star::lang::XTypeProvider
122 Sequence< Type > ORowSetBase::getTypes() throw (RuntimeException, std::exception)
124 return ::comphelper::concatSequences(ORowSetBase_BASE::getTypes(),OPropertyStateContainer::getTypes());
127 // com::sun::star::uno::XInterface
128 Any ORowSetBase::queryInterface( const Type & rType ) throw (RuntimeException, std::exception)
130 Any aRet = ORowSetBase_BASE::queryInterface(rType);
131 if(!aRet.hasValue())
132 aRet = OPropertyStateContainer::queryInterface(rType);
133 return aRet;
136 void SAL_CALL ORowSetBase::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const
138 if(m_pCache)
140 switch(nHandle)
142 case PROPERTY_ID_ROWCOUNT:
143 rValue <<= impl_getRowCount();
144 break;
145 case PROPERTY_ID_ISROWCOUNTFINAL:
146 rValue.setValue(&m_pCache->m_bRowCountFinal,cppu::UnoType<bool>::get());
147 break;
148 default:
149 OPropertyStateContainer::getFastPropertyValue(rValue,nHandle);
152 else
153 OPropertyStateContainer::getFastPropertyValue(rValue,nHandle);
156 // OComponentHelper
157 void SAL_CALL ORowSetBase::disposing()
159 MutexGuard aGuard(*m_pMutex);
161 if ( m_pColumns )
163 TDataColumns().swap(m_aDataColumns);
164 m_pColumns->disposing();
166 if ( m_pCache )
168 m_pCache->deregisterOldRow(m_aOldRow);
169 m_pCache->deleteIterator(this);
171 m_pCache = NULL;
174 // comphelper::OPropertyArrayUsageHelper
175 ::cppu::IPropertyArrayHelper* ORowSetBase::createArrayHelper( ) const
177 Sequence< Property > aProps;
178 describeProperties(aProps);
179 return new ::cppu::OPropertyArrayHelper(aProps);
182 // cppu::OPropertySetHelper
183 ::cppu::IPropertyArrayHelper& SAL_CALL ORowSetBase::getInfoHelper()
185 return *getArrayHelper();
188 // XRow
189 sal_Bool SAL_CALL ORowSetBase::wasNull( ) throw(SQLException, RuntimeException, std::exception)
191 ::osl::MutexGuard aGuard( *m_pMutex );
192 checkCache();
193 return impl_wasNull();
196 bool ORowSetBase::impl_wasNull()
198 return !((m_nLastColumnIndex != -1) && !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is()) || ((*m_aCurrentRow)->get())[m_nLastColumnIndex].isNull();
201 const ORowSetValue& ORowSetBase::getValue(sal_Int32 columnIndex)
203 checkCache();
204 return impl_getValue(columnIndex);
207 const ORowSetValue& ORowSetBase::impl_getValue(sal_Int32 columnIndex)
209 if ( m_bBeforeFirst || m_bAfterLast )
211 SAL_WARN("dbaccess", "ORowSetBase::getValue: Illegal call here (we're before first or after last)!");
212 ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_CURSOR_BEFORE_OR_AFTER ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf );
215 if ( impl_rowDeleted() )
217 return m_aEmptyValue;
220 bool bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
221 if ( !bValidCurrentRow )
223 // currentrow is null when the clone moves the window
224 positionCache( MOVE_NONE );
225 m_aCurrentRow = m_pCache->m_aMatrixIter;
226 m_bIsInsertRow = false;
227 OSL_ENSURE(!m_aCurrentRow.isNull(),"ORowSetBase::getValue: we don't stand on a valid row! Row is null.");
229 bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
232 if ( bValidCurrentRow )
234 #if OSL_DEBUG_LEVEL > 0
235 ORowSetMatrix::iterator aCacheEnd;
236 ORowSetMatrix::iterator aCurrentRow;
237 aCacheEnd = m_pCache->getEnd();
238 aCurrentRow = m_aCurrentRow;
239 ORowSetCacheMap::iterator aCacheIter = m_aCurrentRow.getIter();
240 ORowSetCacheIterator_Helper aHelper = aCacheIter->second;
241 ORowSetMatrix::iterator k = aHelper.aIterator;
242 for (; k != m_pCache->getEnd(); ++k)
244 ORowSetValueVector* pTemp = k->get();
245 OSL_ENSURE( pTemp != reinterpret_cast<void*>(0xfeeefeee),"HALT!" );
247 #endif
248 OSL_ENSURE(!m_aCurrentRow.isNull() && m_aCurrentRow < m_pCache->getEnd() && aCacheIter != m_pCache->m_aCacheIterators.end(),"Invalid iterator set for currentrow!");
249 #if OSL_DEBUG_LEVEL > 0
250 ORowSetRow rRow = (*m_aCurrentRow);
251 OSL_ENSURE(rRow.is() && static_cast<sal_uInt16>(columnIndex) < (rRow->get()).size(),"Invalid size of vector!");
252 #endif
253 return ((*m_aCurrentRow)->get())[m_nLastColumnIndex = columnIndex];
256 // we should normally never reach this
257 return m_aEmptyValue;
260 OUString SAL_CALL ORowSetBase::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
262 ::osl::MutexGuard aGuard( *m_pMutex );
263 return getValue(columnIndex);
266 sal_Bool SAL_CALL ORowSetBase::getBoolean( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
268 ::osl::MutexGuard aGuard( *m_pMutex );
269 return getValue(columnIndex);
272 sal_Int8 SAL_CALL ORowSetBase::getByte( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
274 ::osl::MutexGuard aGuard( *m_pMutex );
275 return getValue(columnIndex);
278 sal_Int16 SAL_CALL ORowSetBase::getShort( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
280 ::osl::MutexGuard aGuard( *m_pMutex );
281 return getValue(columnIndex);
284 sal_Int32 SAL_CALL ORowSetBase::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
286 ::osl::MutexGuard aGuard( *m_pMutex );
287 return getValue(columnIndex);
290 sal_Int64 SAL_CALL ORowSetBase::getLong( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
292 ::osl::MutexGuard aGuard( *m_pMutex );
293 return getValue(columnIndex);
296 float SAL_CALL ORowSetBase::getFloat( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
298 ::osl::MutexGuard aGuard( *m_pMutex );
299 return getValue(columnIndex);
302 double SAL_CALL ORowSetBase::getDouble( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
304 ::osl::MutexGuard aGuard( *m_pMutex );
305 return getValue(columnIndex);
308 Sequence< sal_Int8 > SAL_CALL ORowSetBase::getBytes( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
310 ::osl::MutexGuard aGuard( *m_pMutex );
311 return getValue(columnIndex);
314 ::com::sun::star::util::Date SAL_CALL ORowSetBase::getDate( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
316 ::osl::MutexGuard aGuard( *m_pMutex );
317 return getValue(columnIndex);
320 ::com::sun::star::util::Time SAL_CALL ORowSetBase::getTime( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
322 ::osl::MutexGuard aGuard( *m_pMutex );
323 return getValue(columnIndex);
326 ::com::sun::star::util::DateTime SAL_CALL ORowSetBase::getTimestamp( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
328 ::osl::MutexGuard aGuard( *m_pMutex );
329 return getValue(columnIndex);
332 Reference< ::com::sun::star::io::XInputStream > SAL_CALL ORowSetBase::getBinaryStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
334 ::osl::MutexGuard aGuard( *m_pMutex );
335 checkCache();
337 if ( m_bBeforeFirst || m_bAfterLast )
339 SAL_WARN("dbaccess", "ORowSetBase::getBinaryStream: Illegal call here (we're before first or after last)!");
340 ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_CURSOR_BEFORE_OR_AFTER ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf );
343 if ( impl_rowDeleted() )
345 return NULL;
348 bool bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
349 if ( !bValidCurrentRow )
351 positionCache( MOVE_NONE );
352 m_aCurrentRow = m_pCache->m_aMatrixIter;
353 m_bIsInsertRow = false;
354 OSL_ENSURE(!m_aCurrentRow.isNull(),"ORowSetBase::getBinaryStream: we don't stand on a valid row! Row is null.");
356 bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
359 if ( bValidCurrentRow )
360 return new ::comphelper::SequenceInputStream(((*m_aCurrentRow)->get())[m_nLastColumnIndex = columnIndex].getSequence());
362 // we should normally never reach this
363 return Reference< ::com::sun::star::io::XInputStream >();
366 Reference< ::com::sun::star::io::XInputStream > SAL_CALL ORowSetBase::getCharacterStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
368 return getBinaryStream(columnIndex);
371 Any SAL_CALL ORowSetBase::getObject( sal_Int32 columnIndex, const Reference< XNameAccess >& /*typeMap*/ ) throw(SQLException, RuntimeException, std::exception)
373 ::osl::MutexGuard aGuard( *m_pMutex );
374 checkCache();
376 return getValue(columnIndex).makeAny();
379 Reference< XRef > SAL_CALL ORowSetBase::getRef( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException, std::exception)
381 ::dbtools::throwFeatureNotImplementedSQLException( "XRow::getRef", *m_pMySelf );
382 return NULL;
385 Reference< XBlob > SAL_CALL ORowSetBase::getBlob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
387 return Reference< XBlob >(getValue(columnIndex).makeAny(),UNO_QUERY);
390 Reference< XClob > SAL_CALL ORowSetBase::getClob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
392 return Reference< XClob >(getValue(columnIndex).makeAny(),UNO_QUERY);
395 Reference< XArray > SAL_CALL ORowSetBase::getArray( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException, std::exception)
397 ::dbtools::throwFeatureNotImplementedSQLException( "XRow::getArray", *m_pMySelf );
398 return NULL;
401 // ::com::sun::star::sdbcx::XRowLocate
402 Any SAL_CALL ORowSetBase::getBookmark( ) throw(SQLException, RuntimeException, std::exception)
404 SAL_INFO("dbaccess", "ORowSetBase::getBookmark() Clone = " << m_bClone);
405 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
406 ::osl::MutexGuard aGuard( *m_pMutex );
407 checkCache();
409 if ( m_bBeforeFirst || m_bAfterLast )
410 ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_BOOKMARK_BEFORE_OR_AFTER ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf );
412 if ( impl_rowDeleted() )
413 ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_BOOKMARK_DELETED ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf );
415 OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::getBookmark: bookmark has no value!" );
416 return m_aBookmark;
419 sal_Bool SAL_CALL ORowSetBase::moveToBookmark( const Any& bookmark ) throw(SQLException, RuntimeException, std::exception)
421 SAL_INFO("dbaccess", "ORowSetBase::moveToBookmark(Any) Clone = " << m_bClone);
422 OSL_ENSURE(bookmark.hasValue(),"ORowSetBase::moveToBookmark bookmark has no value!");
423 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
425 if(!bookmark.hasValue() || m_nResultSetType == ResultSetType::FORWARD_ONLY)
427 if(bookmark.hasValue())
428 SAL_WARN("dbaccess", "MoveToBookmark is not possible when we are only forward");
429 else
430 SAL_WARN("dbaccess", "Bookmark is not valid");
431 throwFunctionSequenceException(*m_pMySelf);
434 checkCache();
436 bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
437 if ( bRet )
439 // check if we are inserting a row
440 bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
442 ORowSetNotifier aNotifier( this );
443 // this will call cancelRowModification on the cache if necessary
445 ORowSetRow aOldValues = getOldRow(bWasNew);
447 bRet = m_pCache->moveToBookmark(bookmark);
448 doCancelModification( );
449 if(bRet)
451 // notification order
452 // - column values
453 // - cursorMoved
454 setCurrentRow( true, true, aOldValues, aGuard );
456 else
458 movementFailed();
461 // - IsModified
462 // - IsNew
463 aNotifier.fire( );
465 SAL_INFO("dbaccess", "ORowSetBase::moveToBookmark(Any) = " << bRet << " Clone = " << m_bClone);
466 return bRet;
469 sal_Bool SAL_CALL ORowSetBase::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows ) throw(SQLException, RuntimeException, std::exception)
471 SAL_INFO("dbaccess", "ORowSetBase::moveRelativeToBookmark(Any," << rows << ") Clone = " << m_bClone);
472 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
474 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
476 checkPositioningAllowed();
478 bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
479 if ( bRet )
481 // check if we are inserting a row
482 bool bWasNew = m_pCache->m_bNew || rowDeleted();
484 ORowSetNotifier aNotifier( this );
485 // this will call cancelRowModification on the cache if necessary
487 ORowSetRow aOldValues = getOldRow(bWasNew);
489 bRet = m_pCache->moveRelativeToBookmark(bookmark,rows);
490 doCancelModification( );
491 if(bRet)
493 // notification order
494 // - column values
495 // - cursorMoved
496 setCurrentRow( true, true, aOldValues, aGuard );
498 else
499 movementFailed();
501 // - IsModified
502 // - IsNew
503 aNotifier.fire( );
505 // RowCount/IsRowCountFinal
506 fireRowcount();
508 SAL_INFO("dbaccess", "ORowSetBase::moveRelativeToBookmark(Any," << rows << ") = " << bRet << " Clone = " << m_bClone);
509 return bRet;
512 sal_Int32 SAL_CALL ORowSetBase::compareBookmarks( const Any& _first, const Any& _second ) throw(SQLException, RuntimeException, std::exception)
514 ::osl::MutexGuard aGuard( *m_pMutex );
515 checkCache();
516 return m_pCache->compareBookmarks(_first,_second);
519 sal_Bool SAL_CALL ORowSetBase::hasOrderedBookmarks( ) throw(SQLException, RuntimeException, std::exception)
521 ::osl::MutexGuard aGuard( *m_pMutex );
522 checkCache();
523 return m_pCache->hasOrderedBookmarks();
526 sal_Int32 SAL_CALL ORowSetBase::hashBookmark( const Any& bookmark ) throw(SQLException, RuntimeException, std::exception)
528 ::osl::MutexGuard aGuard( *m_pMutex );
529 checkCache();
530 return m_pCache->hashBookmark(bookmark);
533 // XResultSetMetaDataSupplier
534 Reference< XResultSetMetaData > SAL_CALL ORowSetBase::getMetaData( ) throw(SQLException, RuntimeException, std::exception)
536 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
538 Reference< XResultSetMetaData > xMeta;
539 if(m_pCache)
540 xMeta = m_pCache->getMetaData();
542 return xMeta;
545 // XColumnLocate
546 sal_Int32 SAL_CALL ORowSetBase::findColumn( const OUString& columnName ) throw(SQLException, RuntimeException, std::exception)
548 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
550 ::osl::MutexGuard aGuard( m_aColumnsMutex );
551 // it is possible to save some time here when we remember the names - position relation in a map
552 return m_pColumns ? m_pColumns->findColumn(columnName) : sal_Int32(0);
555 // ::com::sun::star::sdbcx::XColumnsSupplier
556 Reference< XNameAccess > SAL_CALL ORowSetBase::getColumns( ) throw(RuntimeException, std::exception)
558 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
560 ::osl::MutexGuard aGuard( m_aColumnsMutex );
561 if(!m_pColumns)
563 if (!m_pEmptyCollection)
564 m_pEmptyCollection = new OEmptyCollection(*m_pMySelf,m_aColumnsMutex);
565 return m_pEmptyCollection;
568 return m_pColumns;
571 // XResultSet
572 sal_Bool SAL_CALL ORowSetBase::next( ) throw(SQLException, RuntimeException, std::exception)
574 SAL_INFO("dbaccess", "ORowSetBase::next() Clone = " << m_bClone);
575 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
576 checkCache();
578 bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
579 if ( bRet )
581 // check if we are inserting a row
582 bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
584 ORowSetNotifier aNotifier( this );
585 // this will call cancelRowModification on the cache if necessary
587 ORowSetRow aOldValues = getOldRow(bWasNew);
589 positionCache( MOVE_FORWARD );
590 bool bAfterLast = m_pCache->isAfterLast();
591 bRet = m_pCache->next();
592 doCancelModification( );
594 // if we were afterLast before next() then we still are,
595 // i.e. bAfterLast implies m_pCache->isAfterLast()
596 if (bAfterLast)
597 assert(m_pCache->isAfterLast());
598 // so the only way bAfterLast != m_pCache->isAfterLast()
599 // would be that we just arrived there,
600 if (bAfterLast != m_pCache->isAfterLast())
602 assert(!bAfterLast);
603 assert(m_pCache->isAfterLast());
605 // in which case we *did* move the cursor
606 if ( bRet || bAfterLast != m_pCache->isAfterLast() )
608 // notification order
609 // - column values
610 // - cursorMoved
611 setCurrentRow( true, true, aOldValues, aGuard );
612 OSL_ENSURE(!m_bBeforeFirst,"BeforeFirst is true. I don't know why?");
614 else
616 // moved after the last row
617 movementFailed();
618 OSL_ENSURE(m_bAfterLast,"AfterLast is false. I don't know why?");
621 // - IsModified
622 // - IsNew
623 aNotifier.fire();
625 // - RowCount/IsRowCountFinal
626 fireRowcount();
628 SAL_INFO("dbaccess", "ORowSetBase::next() = " << bRet << " Clone = " << m_bClone);
629 return bRet;
632 sal_Bool SAL_CALL ORowSetBase::isBeforeFirst( ) throw(SQLException, RuntimeException, std::exception)
634 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
635 ::osl::MutexGuard aGuard( *m_pMutex );
636 checkCache();
638 SAL_INFO("dbaccess", "ORowSetBase::isBeforeFirst() = " << m_bBeforeFirst << " Clone = " << m_bClone);
640 return m_bBeforeFirst;
643 sal_Bool SAL_CALL ORowSetBase::isAfterLast( ) throw(SQLException, RuntimeException, std::exception)
645 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
646 ::osl::MutexGuard aGuard( *m_pMutex );
647 checkCache();
648 SAL_INFO("dbaccess", "ORowSetBase::isAfterLast() = " << m_bAfterLast << " Clone = " << m_bClone);
650 return m_bAfterLast;
653 bool ORowSetBase::isOnFirst()
655 return isFirst();
658 sal_Bool SAL_CALL ORowSetBase::isFirst( ) throw(SQLException, RuntimeException, std::exception)
660 SAL_INFO("dbaccess", "ORowSetBase::isFirst() Clone = " << m_bClone);
662 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
663 ::osl::MutexGuard aGuard( *m_pMutex );
664 checkCache();
666 if ( m_bBeforeFirst || m_bAfterLast )
667 return sal_False;
669 if ( impl_rowDeleted() )
670 return ( m_nDeletedPosition == 1 );
672 positionCache( MOVE_NONE );
673 bool bIsFirst = m_pCache->isFirst();
675 SAL_INFO("dbaccess", "ORowSetBase::isFirst() = " << bIsFirst << " Clone = " << m_bClone);
676 return bIsFirst;
679 bool ORowSetBase::isOnLast()
681 return isLast();
684 sal_Bool SAL_CALL ORowSetBase::isLast( ) throw(SQLException, RuntimeException, std::exception)
686 SAL_INFO("dbaccess", "ORowSetBase::isLast() Clone = " << m_bClone);
687 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
688 ::osl::MutexGuard aGuard( *m_pMutex );
689 checkCache();
691 if ( m_bBeforeFirst || m_bAfterLast )
692 return sal_False;
694 if ( impl_rowDeleted() )
696 if ( !m_pCache->m_bRowCountFinal )
697 return sal_False;
698 else
699 return ( m_nDeletedPosition == impl_getRowCount() );
702 positionCache( MOVE_NONE );
703 bool bIsLast = m_pCache->isLast();
705 SAL_INFO("dbaccess", "ORowSetBase::isLast() = " << bIsLast << " Clone = " << m_bClone);
706 return bIsLast;
709 void SAL_CALL ORowSetBase::beforeFirst( ) throw(SQLException, RuntimeException, std::exception)
711 SAL_INFO("dbaccess", "ORowSetBase::beforeFirst() Clone = " << m_bClone);
712 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
713 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
715 checkPositioningAllowed();
717 // check if we are inserting a row
718 bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
720 if((bWasNew || !m_bBeforeFirst) && notifyAllListenersCursorBeforeMove(aGuard) )
722 ORowSetNotifier aNotifier( this );
723 // this will call cancelRowModification on the cache if necessary
725 if ( !m_bBeforeFirst )
727 ORowSetRow aOldValues = getOldRow(bWasNew);
728 m_pCache->beforeFirst();
729 doCancelModification( );
731 // notification order
732 // - column values
733 // - cursorMoved
734 setCurrentRow( true, true, aOldValues, aGuard );
736 // - IsModified
737 // - Isnew
738 aNotifier.fire();
740 // - RowCount/IsRowCountFinal
741 fireRowcount();
744 // to be done _after_ the notifications!
745 m_aOldRow->clearRow();
747 SAL_INFO("dbaccess", "ORowSetBase::beforeFirst() Clone = " << m_bClone);
750 void SAL_CALL ORowSetBase::afterLast( ) throw(SQLException, RuntimeException, std::exception)
752 SAL_INFO("dbaccess", "ORowSetBase::afterLast() Clone = " << m_bClone);
753 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
755 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
756 checkPositioningAllowed();
758 bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
760 if((bWasNew || !m_bAfterLast) && notifyAllListenersCursorBeforeMove(aGuard) )
762 // check if we are inserting a row
763 ORowSetNotifier aNotifier( this );
764 // this will call cancelRowModification on the cache if necessary
766 if(!m_bAfterLast)
768 ORowSetRow aOldValues = getOldRow(bWasNew);
770 m_pCache->afterLast();
771 doCancelModification( );
773 // notification order
774 // - column values
775 // - cursorMoved
776 setCurrentRow( true, true, aOldValues, aGuard );
778 // - IsModified
779 // - Isnew
780 aNotifier.fire();
782 // - RowCount/IsRowCountFinal
783 fireRowcount();
786 SAL_INFO("dbaccess", "ORowSetBase::afterLast() Clone = " << m_bClone);
789 bool SAL_CALL ORowSetBase::move( ::std::mem_fun_t<bool,ORowSetBase>& _aCheckFunctor,
790 ::std::mem_fun_t<bool,ORowSetCache>& _aMovementFunctor)
792 SAL_INFO("dbaccess", "ORowSetBase::move() Clone = " << m_bClone);
793 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
794 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
795 checkPositioningAllowed();
797 bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
798 if( bRet )
800 // check if we are inserting a row
801 bool bWasNew = m_pCache->m_bNew || rowDeleted();
803 ORowSetNotifier aNotifier( this );
804 // this will call cancelRowModification on the cache if necessary
806 ORowSetRow aOldValues = getOldRow(bWasNew);
808 bool bMoved = ( bWasNew || !_aCheckFunctor(this) );
810 bRet = _aMovementFunctor(m_pCache);
811 doCancelModification( );
813 if ( bRet )
815 // notification order
816 // - column values
817 // - cursorMoved
818 setCurrentRow( bMoved, true, aOldValues, aGuard );
820 else
821 { // first goes wrong so there is no row
822 movementFailed();
825 // - IsModified
826 // - IsNew
827 aNotifier.fire();
829 // - RowCount/IsRowCountFinal
830 fireRowcount();
832 SAL_INFO("dbaccess", "ORowSetBase::move() = " << bRet << " Clone = " << m_bClone);
833 return bRet;
836 sal_Bool SAL_CALL ORowSetBase::first( ) throw(SQLException, RuntimeException, std::exception)
838 SAL_INFO("dbaccess", "ORowSetBase::first() Clone = " << m_bClone);
839 ::std::mem_fun_t<bool,ORowSetBase> ioF_tmp(&ORowSetBase::isOnFirst);
840 ::std::mem_fun_t<bool,ORowSetCache> F_tmp(&ORowSetCache::first);
841 return move(ioF_tmp,F_tmp);
844 sal_Bool SAL_CALL ORowSetBase::last( ) throw(SQLException, RuntimeException, std::exception)
846 SAL_INFO("dbaccess", "ORowSetBase::last() Clone = " << m_bClone);
847 ::std::mem_fun_t<bool,ORowSetBase> ioL_tmp(&ORowSetBase::isOnLast);
848 ::std::mem_fun_t<bool,ORowSetCache> L_tmp(&ORowSetCache::last);
849 return move(ioL_tmp,L_tmp);
852 sal_Int32 SAL_CALL ORowSetBase::getRow( ) throw(SQLException, RuntimeException, std::exception)
854 SAL_INFO("dbaccess", "ORowSetBase::getRow() Clone = " << m_bClone);
855 ::osl::MutexGuard aGuard( *m_pMutex );
857 checkCache();
858 return impl_getRow();
861 sal_Int32 ORowSetBase::impl_getRow()
863 sal_Int32 nPos = 0;
864 if ( m_bBeforeFirst )
865 nPos = 0;
866 else if ( m_bAfterLast )
867 nPos = impl_getRowCount() + 1;
868 else if ( impl_rowDeleted() )
869 nPos = m_nDeletedPosition;
870 else if ( !m_bClone && m_pCache->m_bNew )
871 nPos = 0;
872 else
874 positionCache( MOVE_NONE );
875 nPos = m_pCache->getRow();
877 SAL_INFO("dbaccess", "ORowSetBase::impl_getRow() = " << nPos << " Clone = " << m_bClone);
878 return nPos;
881 sal_Bool SAL_CALL ORowSetBase::absolute( sal_Int32 row ) throw(SQLException, RuntimeException, std::exception)
883 SAL_INFO("dbaccess", "ORowSetBase::absolute(" << row << ") Clone = " << m_bClone);
884 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
885 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
886 checkPositioningAllowed();
888 bool bRet = ( row > 0 )
889 && notifyAllListenersCursorBeforeMove( aGuard );
890 if ( bRet )
892 // check if we are inserting a row
893 bool bWasNew = m_pCache->m_bNew || rowDeleted();
895 ORowSetNotifier aNotifier( this );
896 // this will call cancelRowModification on the cache if necessary
898 ORowSetRow aOldValues = getOldRow(bWasNew);
900 bRet = m_pCache->absolute(row);
901 doCancelModification( );
903 if(bRet)
905 // notification order
906 // - column values
907 // - cursorMoved
908 setCurrentRow( true, true, aOldValues, aGuard );
910 else
911 { // absolute movement goes wrong we stand left or right side of the rows
912 movementFailed();
915 // - IsModified
916 // - IsNew
917 aNotifier.fire();
919 // - RowCount/IsRowCountFinal
920 fireRowcount();
922 SAL_INFO("dbaccess", "ORowSetBase::absolute(" << row << ") = " << bRet << " Clone = " << m_bClone);
923 return bRet;
926 sal_Bool SAL_CALL ORowSetBase::relative( sal_Int32 rows ) throw(SQLException, RuntimeException, std::exception)
928 SAL_INFO("dbaccess", "ORowSetBase::relative(" << rows << ") Clone = " << m_bClone);
929 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
931 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
933 if(!rows)
934 return sal_True; // in this case do nothing
936 checkPositioningAllowed();
938 bool bRet =
939 ( ( !m_bAfterLast || rows <= 0 )
940 && ( !m_bBeforeFirst || rows >= 0 )
941 && notifyAllListenersCursorBeforeMove( aGuard )
944 if ( bRet )
946 // check if we are inserting a row
947 bool bWasNew = m_pCache->m_bNew || rowDeleted();
949 ORowSetNotifier aNotifier( this );
950 // this will call cancelRowModification on the cache if necessary
952 ORowSetRow aOldValues = getOldRow(bWasNew);
954 positionCache( rows > 0 ? MOVE_FORWARD : MOVE_BACKWARD );
955 bRet = m_pCache->relative(rows);
956 doCancelModification( );
958 if(bRet)
960 // notification order
961 // - column values
962 // - cursorMoved
963 setCurrentRow( true, true, aOldValues, aGuard );
965 else
967 movementFailed();
970 // - IsModified
971 // - IsNew
972 aNotifier.fire();
974 // - RowCount/IsRowCountFinal
975 fireRowcount();
977 SAL_INFO("dbaccess", "ORowSetBase::relative(" << rows << ") = " << bRet << " Clone = " << m_bClone);
978 return bRet;
981 sal_Bool SAL_CALL ORowSetBase::previous( ) throw(SQLException, RuntimeException, std::exception)
983 SAL_INFO("dbaccess", "ORowSetBase::previous() Clone = " << m_bClone);
984 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
985 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
987 checkPositioningAllowed();
989 bool bRet = !m_bBeforeFirst
990 && notifyAllListenersCursorBeforeMove(aGuard);
992 if ( bRet )
994 // check if we are inserting a row
995 bool bWasNew = m_pCache->m_bNew || rowDeleted();
997 ORowSetNotifier aNotifier( this );
998 // this will call cancelRowModification on the cache if necessary
1000 ORowSetRow aOldValues = getOldRow(bWasNew);
1002 positionCache( MOVE_BACKWARD );
1003 bRet = m_pCache->previous();
1004 doCancelModification( );
1006 // if m_bBeforeFirst is false and bRet is false than we stood on the first row
1007 if(!m_bBeforeFirst || bRet)
1009 // notification order
1010 // - column values
1011 // - cursorMoved
1012 setCurrentRow( true, true, aOldValues, aGuard );
1014 else
1016 SAL_WARN("dbaccess", "ORowSetBase::previous: inconsistency!" );
1017 // we should never reach this place, as we should not get into this whole branch if m_bBeforeFirst
1018 // was |true| from the beginning
1019 movementFailed();
1022 // - IsModified
1023 // - IsNew
1024 aNotifier.fire();
1026 // - RowCount/IsRowCountFinal
1027 fireRowcount();
1029 SAL_INFO("dbaccess", "ORowSetBase::previous() = " << bRet << " Clone = " << m_bClone);
1030 return bRet;
1033 void ORowSetBase::setCurrentRow( bool _bMoved, bool _bDoNotify, const ORowSetRow& _rOldValues, ::osl::ResettableMutexGuard& _rGuard )
1035 SAL_INFO("dbaccess", "ORowSetBase::setCurrentRow() Clone = " << m_bClone);
1036 m_bBeforeFirst = m_pCache->isBeforeFirst();
1037 m_bAfterLast = m_pCache->isAfterLast();
1039 if(!(m_bBeforeFirst || m_bAfterLast))
1041 m_aBookmark = m_pCache->getBookmark();
1042 OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!");
1043 m_aCurrentRow = m_pCache->m_aMatrixIter;
1044 m_bIsInsertRow = false;
1045 OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is null!");
1046 m_aCurrentRow.setBookmark(m_aBookmark);
1047 OSL_ENSURE(!m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd(),"Position of matrix iterator isn't valid!");
1048 OSL_ENSURE(m_aCurrentRow->is(),"Currentrow isn't valid");
1049 OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!");
1051 m_aCurrentRow = m_pCache->m_aMatrixIter;
1052 m_bIsInsertRow = false;
1053 OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is nul after positionCache!");
1054 #if OSL_DEBUG_LEVEL > 0
1055 ORowSetRow rRow = (*m_aCurrentRow);
1056 OSL_ENSURE(rRow.is() ,"Invalid size of vector!");
1057 #endif
1059 // notification order
1060 // - column values
1061 if ( _bDoNotify )
1062 firePropertyChange(_rOldValues);
1065 else
1067 m_aOldRow->clearRow();
1068 m_aCurrentRow = m_pCache->getEnd();
1069 m_aBookmark = Any();
1070 m_aCurrentRow.setBookmark(m_aBookmark);
1073 // TODO: can this be done before the notifications?
1074 if(!(m_bBeforeFirst || m_bAfterLast) && !m_aCurrentRow.isNull() && m_aCurrentRow->is() && m_aCurrentRow != m_pCache->getEnd())
1075 m_aOldRow->setRow(new ORowSetValueVector( *(*m_aCurrentRow) ));
1077 if ( _bMoved && _bDoNotify )
1078 // - cursorMoved
1079 notifyAllListenersCursorMoved( _rGuard );
1081 SAL_INFO("dbaccess", "ORowSetBase::setCurrentRow() Clone = " << m_bClone);
1084 void ORowSetBase::checkPositioningAllowed() throw( SQLException, RuntimeException )
1086 if(!m_pCache || m_nResultSetType == ResultSetType::FORWARD_ONLY)
1087 throwFunctionSequenceException(*m_pMySelf);
1090 Reference< XInterface > ORowSetBase::getStatement() throw( SQLException, RuntimeException, std::exception )
1092 return NULL;
1095 void SAL_CALL ORowSetBase::refreshRow( ) throw(SQLException, RuntimeException, std::exception)
1097 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
1098 ::osl::MutexGuard aGuard( *m_pMutex );
1099 checkCache();
1100 if ( impl_rowDeleted() )
1101 throwSQLException( "The current row is deleted", SQL_INVALID_CURSOR_STATE, Reference< XRowSet >( this ) );
1103 if(!(m_bBeforeFirst || m_bAfterLast))
1105 bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
1106 ORowSetRow aOldValues = getOldRow(bWasNew);
1107 positionCache( MOVE_NONE );
1108 m_pCache->refreshRow();
1109 firePropertyChange(aOldValues);
1113 sal_Bool SAL_CALL ORowSetBase::rowUpdated( ) throw(SQLException, RuntimeException, std::exception)
1115 ::osl::MutexGuard aGuard( *m_pMutex );
1116 checkCache();
1118 if ( impl_rowDeleted() )
1119 return sal_False;
1121 return m_pCache->rowUpdated();
1124 sal_Bool SAL_CALL ORowSetBase::rowInserted( ) throw(SQLException, RuntimeException, std::exception)
1126 ::osl::MutexGuard aGuard( *m_pMutex );
1128 checkCache();
1130 if ( impl_rowDeleted() )
1131 return sal_False;
1133 return m_pCache->rowInserted();
1136 sal_Bool SAL_CALL ORowSetBase::rowDeleted( ) throw(SQLException, RuntimeException, std::exception)
1138 ::osl::MutexGuard aGuard( *m_pMutex );
1139 checkCache();
1140 return impl_rowDeleted();
1143 bool ORowSetBase::impl_rowDeleted( )
1145 return !m_aBookmark.hasValue() && !m_bBeforeFirst && !m_bAfterLast;
1148 // XWarningsSupplier
1149 Any SAL_CALL ORowSetBase::getWarnings( ) throw(SQLException, RuntimeException, std::exception)
1151 ::osl::MutexGuard aGuard( *m_pMutex );
1153 if ( m_pCache )
1155 Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY );
1156 if ( xWarnings.is() )
1157 return xWarnings->getWarnings();
1160 return Any();
1163 void SAL_CALL ORowSetBase::clearWarnings( ) throw(SQLException, RuntimeException, std::exception)
1165 ::osl::MutexGuard aGuard( *m_pMutex );
1167 if ( m_pCache )
1169 Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY );
1170 if ( xWarnings.is() )
1171 xWarnings->clearWarnings();
1175 void ORowSetBase::firePropertyChange(const ORowSetRow& _rOldRow)
1177 if (!isPropertyChangeNotificationEnabled())
1178 return;
1180 SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange" );
1181 SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange() Clone = " << m_bClone);
1182 OSL_ENSURE(m_pColumns,"Columns can not be NULL here!");
1183 sal_Int32 i=0;
1184 TDataColumns::iterator aEnd = m_aDataColumns.end();
1185 for(TDataColumns::iterator aIter = m_aDataColumns.begin();aIter != aEnd;++aIter,++i)
1189 (*aIter)->fireValueChange(_rOldRow.is() ? (_rOldRow->get())[i+1] : ::connectivity::ORowSetValue());
1191 catch (const Exception&)
1193 SAL_WARN("dbaccess", "firePropertyChange: Exception on column " << i);
1196 SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange() Clone = " << m_bClone);
1199 void ORowSetBase::firePropertyChange(sal_Int32 _nPos,const ::connectivity::ORowSetValue& _rOldValue)
1201 OSL_ENSURE(_nPos < (sal_Int32)m_aDataColumns.size(),"nPos is invalid!");
1202 m_aDataColumns[_nPos]->fireValueChange(_rOldValue);
1205 void ORowSetBase::fireRowcount()
1209 bool ORowSetBase::notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& /*_rGuard*/)
1211 return true;
1214 void ORowSetBase::notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& /*_rGuard*/)
1218 void ORowSetBase::notifyAllListeners(::osl::ResettableMutexGuard& /*_rGuard*/)
1222 bool ORowSetBase::isPropertyChangeNotificationEnabled() const
1224 return true;
1227 void ORowSetBase::fireProperty( sal_Int32 _nProperty, bool _bNew, bool _bOld )
1229 Any aNew = css::uno::makeAny( _bNew );
1230 Any aOld = css::uno::makeAny( _bOld );
1231 fire( &_nProperty, &aNew, &aOld, 1, sal_False );
1234 void ORowSetBase::positionCache( CursorMoveDirection _ePrepareForDirection )
1236 SAL_INFO("dbaccess", "ORowSetBase::positionCache() Clone = " << m_bClone);
1238 bool bSuccess = false;
1239 if ( m_aBookmark.hasValue() )
1241 if (_ePrepareForDirection == MOVE_NONE_REFRESH ||
1242 (m_pCache->isAfterLast() != bool(isAfterLast())) || ( m_pCache->isBeforeFirst() != bool(isBeforeFirst()) ) ||
1243 m_pCache->compareBookmarks( m_aBookmark, m_pCache->getBookmark() ) != CompareBookmark::EQUAL )
1244 bSuccess = m_pCache->moveToBookmark( m_aBookmark );
1245 else
1246 bSuccess = true;
1248 else
1250 if ( m_bBeforeFirst )
1252 bSuccess = m_pCache->beforeFirst();
1254 else if ( m_bAfterLast )
1256 bSuccess = m_pCache->afterLast();
1258 else
1260 OSL_ENSURE( m_nDeletedPosition >= 1, "ORowSetBase::positionCache: no bookmark, and no valid 'deleted position'!" );
1261 switch ( _ePrepareForDirection )
1263 case MOVE_FORWARD:
1264 if ( m_nDeletedPosition > 1 )
1265 bSuccess = m_pCache->absolute( m_nDeletedPosition - 1 );
1266 else
1268 m_pCache->beforeFirst();
1269 bSuccess = true;
1271 break;
1273 case MOVE_BACKWARD:
1274 if ( m_pCache->m_bRowCountFinal && ( m_nDeletedPosition == impl_getRowCount() ) )
1276 m_pCache->afterLast();
1277 bSuccess = true;
1279 else
1280 bSuccess = m_pCache->absolute( m_nDeletedPosition );
1281 break;
1283 case MOVE_NONE:
1284 case MOVE_NONE_REFRESH:
1285 bSuccess = false; // will be asserted below
1286 break;
1290 OSL_ENSURE( bSuccess, "ORowSetBase::positionCache: failed!" );
1291 (void)bSuccess;
1293 SAL_INFO("dbaccess", "ORowSetBase::positionCache() Clone = " << m_bClone);
1296 void ORowSetBase::checkCache()
1298 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
1299 if(!m_pCache)
1300 throwFunctionSequenceException(*m_pMySelf);
1303 void ORowSetBase::movementFailed()
1305 SAL_INFO("dbaccess", "ORowSetBase::movementFailed() Clone = " << m_bClone);
1306 m_aOldRow->clearRow();
1307 m_aCurrentRow = m_pCache->getEnd();
1308 m_bBeforeFirst = m_pCache->isBeforeFirst();
1309 m_bAfterLast = m_pCache->isAfterLast();
1310 m_aBookmark = Any();
1311 m_aCurrentRow.setBookmark(m_aBookmark);
1312 OSL_ENSURE(m_bBeforeFirst || m_bAfterLast,"BeforeFirst or AfterLast is wrong!");
1313 SAL_INFO("dbaccess", "ORowSetBase::movementFailed() Clone = " << m_bClone);
1316 ORowSetRow ORowSetBase::getOldRow(bool _bWasNew)
1318 OSL_ENSURE(m_aOldRow.is(),"RowSetRowHElper isn't valid!");
1319 ORowSetRow aOldValues;
1320 if ( !_bWasNew && m_aOldRow->getRow().is() )
1321 aOldValues = new ORowSetValueVector( *(m_aOldRow->getRow())); // remember the old values
1322 return aOldValues;
1325 void ORowSetBase::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const
1327 _rDefault.clear();
1330 void ORowSetBase::onDeleteRow( const Any& _rBookmark )
1332 if ( rowDeleted() )
1333 // not interested in
1334 return;
1336 ::osl::MutexGuard aGuard( *m_pMutex );
1337 //OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::onDeleteRow: Bookmark isn't valid!" );
1338 if ( compareBookmarks( _rBookmark, m_aBookmark ) == CompareBookmark::EQUAL )
1340 positionCache( MOVE_NONE );
1341 m_nDeletedPosition = m_pCache->getRow();
1345 void ORowSetBase::onDeletedRow( const Any& _rBookmark, sal_Int32 _nPos )
1347 if ( rowDeleted() )
1349 // if we're a clone, and on a deleted row, and the main RowSet deleted another
1350 // row (only the main RowSet can, clones can't), which is *before* our
1351 // deleted position, then we have to adjust this position
1352 if ( m_bClone && ( _nPos < m_nDeletedPosition ) )
1353 --m_nDeletedPosition;
1354 return;
1357 ::osl::MutexGuard aGuard( *m_pMutex );
1358 if ( compareBookmarks( _rBookmark, m_aBookmark ) == CompareBookmark::EQUAL )
1360 m_aOldRow->clearRow();
1361 m_aCurrentRow = m_pCache->getEnd();
1362 m_aBookmark = Any();
1363 m_aCurrentRow.setBookmark( m_aBookmark );
1367 sal_Int32 ORowSetBase::impl_getRowCount() const
1369 sal_Int32 nRowCount( m_pCache->m_nRowCount );
1370 if ( const_cast< ORowSetBase* >( this )->rowDeleted() && !m_pCache->m_bNew )
1371 ++nRowCount;
1372 return nRowCount;
1375 struct ORowSetNotifierImpl
1377 ::std::vector<sal_Int32> aChangedColumns;
1378 ::std::vector<Any> aChangedBookmarks;
1379 ORowSetValueVector::Vector aRow;
1384 ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet )
1385 :m_pRowSet( _pRowSet )
1386 ,m_bWasNew( false )
1387 ,m_bWasModified( false )
1388 #ifdef DBG_UTIL
1389 ,m_bNotifyCalled( false )
1390 #endif
1393 OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This wil crash." );
1395 // remember the "inserted" and "modified" state for later firing
1396 m_bWasNew = m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() );
1397 m_bWasModified = m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() );
1399 // if the row set is on the insert row, then we need to cancel this
1400 if ( m_pRowSet->isModification( ORowSetBase::GrantNotifierAccess() ) )
1401 m_pRowSet->doCancelModification( ORowSetBase::GrantNotifierAccess() );
1404 ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet,const ORowSetValueVector::Vector& i_aRow )
1405 :m_pImpl(new ORowSetNotifierImpl)
1406 ,m_pRowSet( _pRowSet )
1407 ,m_bWasNew( false )
1408 ,m_bWasModified( false )
1409 #ifdef DBG_UTIL
1410 ,m_bNotifyCalled( false )
1411 #endif
1414 OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This wil crash." );
1415 m_pImpl->aRow = i_aRow; // yes, create a copy to store the old values
1418 ORowSetNotifier::~ORowSetNotifier( )
1422 void ORowSetNotifier::fire()
1424 // we're not interested in firing changes FALSE->TRUE, only TRUE->FALSE.
1425 // (the former would be quite pathological, e.g. after a failed movement)
1427 if ( m_bWasModified
1428 && ( m_bWasModified != m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() ) )
1430 m_pRowSet->fireProperty( PROPERTY_ID_ISMODIFIED, false, true, ORowSetBase::GrantNotifierAccess() );
1432 if ( m_bWasNew
1433 && ( m_bWasNew != m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() ) )
1435 m_pRowSet->fireProperty( PROPERTY_ID_ISNEW, false, true, ORowSetBase::GrantNotifierAccess() );
1437 #ifdef DBG_UTIL
1438 m_bNotifyCalled = true;
1439 #endif
1442 ::std::vector<sal_Int32>& ORowSetNotifier::getChangedColumns() const
1444 OSL_ENSURE(m_pImpl.get(),"Illegal CTor call, use the other one!");
1445 return m_pImpl->aChangedColumns;
1448 void ORowSetNotifier::firePropertyChange()
1450 OSL_ENSURE(m_pImpl.get(),"Illegal CTor call, use the other one!");
1451 if( m_pImpl.get() )
1453 ::std::vector<sal_Int32>::iterator aIter = m_pImpl->aChangedColumns.begin();
1454 for(;aIter != m_pImpl->aChangedColumns.end();++aIter)
1456 m_pRowSet->firePropertyChange((*aIter)-1 ,m_pImpl->aRow[(*aIter)-1], ORowSetBase::GrantNotifierAccess());
1458 if ( !m_pImpl->aChangedColumns.empty() )
1459 m_pRowSet->fireProperty(PROPERTY_ID_ISMODIFIED,true,false, ORowSetBase::GrantNotifierAccess());
1463 } // namespace dbaccess
1465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */