calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / dbaccess / source / core / api / RowSetBase.cxx
blob753c857eecc08088027e0dd68f6a23005d3e8cce
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 <stringconstants.hxx>
25 #include <sal/log.hxx>
26 #include <core_resource.hxx>
27 #include <strings.hrc>
28 #include <strings.hxx>
29 #include <com/sun/star/beans/PropertyAttribute.hpp>
30 #include <com/sun/star/sdbcx/CompareBookmark.hpp>
31 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
32 #include <com/sun/star/sdbc/ResultSetType.hpp>
33 #include <comphelper/sequence.hxx>
34 #include <comphelper/seqstream.hxx>
35 #include <connectivity/dbexception.hxx>
36 #include <o3tl/safeint.hxx>
37 #include <comphelper/diagnose_ex.hxx>
39 using namespace dbaccess;
40 using namespace connectivity;
41 using namespace connectivity::sdbcx;
42 using namespace comphelper;
43 using namespace dbtools;
44 using namespace ::com::sun::star::uno;
45 using namespace ::com::sun::star::beans;
46 using namespace ::com::sun::star::sdbc;
47 using namespace ::com::sun::star::sdb;
48 using namespace ::com::sun::star::sdbcx;
49 using namespace ::com::sun::star::container;
50 using namespace ::com::sun::star::lang;
51 using namespace ::com::sun::star::util;
52 using namespace ::cppu;
53 using namespace ::osl;
55 namespace dbaccess
58 // OEmptyCollection
59 class OEmptyCollection : public sdbcx::OCollection
61 protected:
62 virtual void impl_refresh() override;
63 virtual connectivity::sdbcx::ObjectType createObject(const OUString& _rName) override;
64 public:
65 OEmptyCollection(::cppu::OWeakObject& _rParent,::osl::Mutex& _rMutex) : OCollection(_rParent, true, _rMutex, std::vector< OUString>()){}
68 void OEmptyCollection::impl_refresh()
72 connectivity::sdbcx::ObjectType OEmptyCollection::createObject(const OUString& /*_rName*/)
74 return connectivity::sdbcx::ObjectType();
77 // ORowSetBase
79 ORowSetBase::ORowSetBase( const Reference<XComponentContext>& _rContext, ::cppu::OBroadcastHelper& _rBHelper, ::osl::Mutex* _pMutex )
80 :OPropertyStateContainer(_rBHelper)
81 ,m_pMutex(_pMutex)
82 ,m_pMySelf(nullptr)
83 ,m_rBHelper(_rBHelper)
84 ,m_aContext( _rContext )
85 ,m_nLastColumnIndex(-1)
86 ,m_nDeletedPosition(-1)
87 ,m_nResultSetType( ResultSetType::FORWARD_ONLY )
88 ,m_nResultSetConcurrency( ResultSetConcurrency::READ_ONLY )
89 ,m_bClone(false)
90 ,m_bIgnoreResult(false)
91 ,m_bBeforeFirst(true) // changed from sal_False
92 ,m_bAfterLast(false)
93 ,m_bIsInsertRow(false)
95 sal_Int32 nRBT = PropertyAttribute::READONLY | PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT;
97 registerPropertyNoMember( PROPERTY_ROWCOUNT, PROPERTY_ID_ROWCOUNT, nRBT, cppu::UnoType<sal_Int32>::get(), css::uno::Any(sal_Int32(0)) );
98 registerPropertyNoMember( PROPERTY_ISROWCOUNTFINAL, PROPERTY_ID_ISROWCOUNTFINAL, nRBT, cppu::UnoType<bool>::get(), css::uno::Any(false) );
101 ORowSetBase::~ORowSetBase()
103 if(m_pColumns)
105 TDataColumns().swap(m_aDataColumns);
106 m_pColumns->acquire();
107 m_pColumns->disposing();
111 // css::lang::XTypeProvider
112 Sequence< Type > ORowSetBase::getTypes()
114 return ::comphelper::concatSequences(ORowSetBase_BASE::getTypes(),OPropertyStateContainer::getTypes());
117 // css::uno::XInterface
118 Any ORowSetBase::queryInterface( const Type & rType )
120 Any aRet = ORowSetBase_BASE::queryInterface(rType);
121 if(!aRet.hasValue())
122 aRet = OPropertyStateContainer::queryInterface(rType);
123 return aRet;
126 void SAL_CALL ORowSetBase::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const
128 if(m_pCache)
130 switch(nHandle)
132 case PROPERTY_ID_ROWCOUNT:
133 rValue <<= impl_getRowCount();
134 break;
135 case PROPERTY_ID_ISROWCOUNTFINAL:
136 rValue <<= m_pCache->m_bRowCountFinal;
137 break;
138 default:
139 OPropertyStateContainer::getFastPropertyValue(rValue,nHandle);
142 else
143 OPropertyStateContainer::getFastPropertyValue(rValue,nHandle);
146 // OComponentHelper
147 void SAL_CALL ORowSetBase::disposing()
149 MutexGuard aGuard(*m_pMutex);
151 if ( m_pColumns )
153 TDataColumns().swap(m_aDataColumns);
154 m_pColumns->disposing();
156 if ( m_pCache )
158 m_pCache->deregisterOldRow(m_aOldRow);
159 m_pCache->deleteIterator(this);
161 m_pCache = nullptr;
164 // comphelper::OPropertyArrayUsageHelper
165 ::cppu::IPropertyArrayHelper* ORowSetBase::createArrayHelper( ) const
167 Sequence< Property > aProps;
168 describeProperties(aProps);
169 return new ::cppu::OPropertyArrayHelper(aProps);
172 // cppu::OPropertySetHelper
173 ::cppu::IPropertyArrayHelper& SAL_CALL ORowSetBase::getInfoHelper()
175 return *getArrayHelper();
178 // XRow
179 sal_Bool SAL_CALL ORowSetBase::wasNull( )
181 ::osl::MutexGuard aGuard( *m_pMutex );
182 checkCache();
183 return !((m_nLastColumnIndex != -1) && !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is())
184 || (**m_aCurrentRow)[m_nLastColumnIndex].isNull();
187 const ORowSetValue& ORowSetBase::getValue(sal_Int32 columnIndex)
189 checkCache();
190 return impl_getValue(columnIndex);
193 const ORowSetValue& ORowSetBase::impl_getValue(sal_Int32 columnIndex)
195 if ( m_bBeforeFirst || m_bAfterLast )
197 SAL_WARN("dbaccess", "ORowSetBase::getValue: Illegal call here (we're before first or after last)!");
198 ::dbtools::throwSQLException( DBA_RES( RID_STR_CURSOR_BEFORE_OR_AFTER ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );
201 if ( impl_rowDeleted() )
203 return m_aEmptyValue;
206 bool bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
207 if ( !bValidCurrentRow )
209 // currentrow is null when the clone moves the window
210 positionCache( CursorMoveDirection::Current );
211 m_aCurrentRow = m_pCache->m_aMatrixIter;
212 m_bIsInsertRow = false;
213 OSL_ENSURE(!m_aCurrentRow.isNull(),"ORowSetBase::getValue: we don't stand on a valid row! Row is null.");
215 bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
218 if ( bValidCurrentRow )
220 #if OSL_DEBUG_LEVEL > 0
221 ORowSetMatrix::const_iterator aCacheEnd;
222 ORowSetMatrix::iterator aCurrentRow;
223 aCacheEnd = m_pCache->getEnd();
224 aCurrentRow = m_aCurrentRow;
225 ORowSetCacheMap::const_iterator aCacheIter = m_aCurrentRow.getIter();
226 ORowSetCacheIterator_Helper aHelper = aCacheIter->second;
227 ORowSetMatrix::const_iterator k = aHelper.aIterator;
228 for (; k != m_pCache->getEnd(); ++k)
230 ORowSetValueVector* pTemp = k->get();
231 OSL_ENSURE( pTemp != reinterpret_cast<void*>(0xfeeefeee),"HALT!" );
233 OSL_ENSURE(!m_aCurrentRow.isNull() && m_aCurrentRow < m_pCache->getEnd() && aCacheIter != m_pCache->m_aCacheIterators.end(),"Invalid iterator set for currentrow!");
234 #endif
235 ORowSetRow rRow = *m_aCurrentRow;
236 bool bValidPosition = rRow.is() && o3tl::make_unsigned(columnIndex) < rRow->size();
237 if (!bValidPosition)
239 SAL_WARN("dbaccess", "ORowSetBase::getValue: Invalid size of vector!");
240 ::dbtools::throwSQLException( DBA_RES( RID_STR_CURSOR_BEFORE_OR_AFTER ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );
242 m_nLastColumnIndex = columnIndex;
243 return (*rRow)[m_nLastColumnIndex];
246 // we should normally never reach this
247 return m_aEmptyValue;
250 OUString SAL_CALL ORowSetBase::getString( sal_Int32 columnIndex )
252 ::osl::MutexGuard aGuard( *m_pMutex );
253 return getValue(columnIndex).getString();
256 sal_Bool SAL_CALL ORowSetBase::getBoolean( sal_Int32 columnIndex )
258 ::osl::MutexGuard aGuard( *m_pMutex );
259 return getValue(columnIndex).getBool();
262 sal_Int8 SAL_CALL ORowSetBase::getByte( sal_Int32 columnIndex )
264 ::osl::MutexGuard aGuard( *m_pMutex );
265 return getValue(columnIndex).getInt8();
268 sal_Int16 SAL_CALL ORowSetBase::getShort( sal_Int32 columnIndex )
270 ::osl::MutexGuard aGuard( *m_pMutex );
271 return getValue(columnIndex).getInt16();
274 sal_Int32 SAL_CALL ORowSetBase::getInt( sal_Int32 columnIndex )
276 ::osl::MutexGuard aGuard( *m_pMutex );
277 return getValue(columnIndex).getInt32();
280 sal_Int64 SAL_CALL ORowSetBase::getLong( sal_Int32 columnIndex )
282 ::osl::MutexGuard aGuard( *m_pMutex );
283 return getValue(columnIndex).getLong();
286 float SAL_CALL ORowSetBase::getFloat( sal_Int32 columnIndex )
288 ::osl::MutexGuard aGuard( *m_pMutex );
289 return getValue(columnIndex).getFloat();
292 double SAL_CALL ORowSetBase::getDouble( sal_Int32 columnIndex )
294 ::osl::MutexGuard aGuard( *m_pMutex );
295 return getValue(columnIndex).getDouble();
298 Sequence< sal_Int8 > SAL_CALL ORowSetBase::getBytes( sal_Int32 columnIndex )
300 ::osl::MutexGuard aGuard( *m_pMutex );
301 return getValue(columnIndex).getSequence();
304 css::util::Date SAL_CALL ORowSetBase::getDate( sal_Int32 columnIndex )
306 ::osl::MutexGuard aGuard( *m_pMutex );
307 return getValue(columnIndex).getDate();
310 css::util::Time SAL_CALL ORowSetBase::getTime( sal_Int32 columnIndex )
312 ::osl::MutexGuard aGuard( *m_pMutex );
313 return getValue(columnIndex).getTime();
316 css::util::DateTime SAL_CALL ORowSetBase::getTimestamp( sal_Int32 columnIndex )
318 ::osl::MutexGuard aGuard( *m_pMutex );
319 return getValue(columnIndex).getDateTime();
322 Reference< css::io::XInputStream > SAL_CALL ORowSetBase::getBinaryStream( sal_Int32 columnIndex )
324 ::osl::MutexGuard aGuard( *m_pMutex );
325 checkCache();
327 if ( m_bBeforeFirst || m_bAfterLast )
329 SAL_WARN("dbaccess", "ORowSetBase::getBinaryStream: Illegal call here (we're before first or after last)!");
330 ::dbtools::throwSQLException( DBA_RES( RID_STR_CURSOR_BEFORE_OR_AFTER ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );
333 if ( impl_rowDeleted() )
335 return nullptr;
338 bool bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
339 if ( !bValidCurrentRow )
341 positionCache( CursorMoveDirection::Current );
342 m_aCurrentRow = m_pCache->m_aMatrixIter;
343 m_bIsInsertRow = false;
344 OSL_ENSURE(!m_aCurrentRow.isNull(),"ORowSetBase::getBinaryStream: we don't stand on a valid row! Row is null.");
346 bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
349 if ( bValidCurrentRow )
351 m_nLastColumnIndex = columnIndex;
352 return new ::comphelper::SequenceInputStream((**m_aCurrentRow)[m_nLastColumnIndex].getSequence());
355 // we should normally never reach this
356 return Reference< css::io::XInputStream >();
359 Reference< css::io::XInputStream > SAL_CALL ORowSetBase::getCharacterStream( sal_Int32 columnIndex )
361 return getBinaryStream(columnIndex);
364 Any SAL_CALL ORowSetBase::getObject( sal_Int32 columnIndex, const Reference< XNameAccess >& /*typeMap*/ )
366 ::osl::MutexGuard aGuard( *m_pMutex );
367 checkCache();
369 return getValue(columnIndex).makeAny();
372 Reference< XRef > SAL_CALL ORowSetBase::getRef( sal_Int32 /*columnIndex*/ )
374 ::dbtools::throwFeatureNotImplementedSQLException( "XRow::getRef", *m_pMySelf );
375 return nullptr;
378 Reference< XBlob > SAL_CALL ORowSetBase::getBlob( sal_Int32 columnIndex )
380 return Reference< XBlob >(getValue(columnIndex).makeAny(),UNO_QUERY);
383 Reference< XClob > SAL_CALL ORowSetBase::getClob( sal_Int32 columnIndex )
385 return Reference< XClob >(getValue(columnIndex).makeAny(),UNO_QUERY);
388 Reference< XArray > SAL_CALL ORowSetBase::getArray( sal_Int32 /*columnIndex*/ )
390 ::dbtools::throwFeatureNotImplementedSQLException( "XRow::getArray", *m_pMySelf );
391 return nullptr;
394 // css::sdbcx::XRowLocate
395 Any SAL_CALL ORowSetBase::getBookmark( )
397 SAL_INFO("dbaccess", "ORowSetBase::getBookmark() Clone = " << m_bClone);
398 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
399 ::osl::MutexGuard aGuard( *m_pMutex );
400 checkCache();
402 if ( m_bBeforeFirst || m_bAfterLast )
403 ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_BOOKMARK_BEFORE_OR_AFTER ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );
405 if ( impl_rowDeleted() )
406 ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_BOOKMARK_DELETED ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );
408 OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::getBookmark: bookmark has no value!" );
409 return m_aBookmark;
412 sal_Bool SAL_CALL ORowSetBase::moveToBookmark( const Any& bookmark )
414 SAL_INFO("dbaccess", "ORowSetBase::moveToBookmark(Any) Clone = " << m_bClone);
415 OSL_ENSURE(bookmark.hasValue(),"ORowSetBase::moveToBookmark bookmark has no value!");
416 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
418 if(!bookmark.hasValue() || m_nResultSetType == ResultSetType::FORWARD_ONLY)
420 if(bookmark.hasValue())
421 SAL_WARN("dbaccess", "MoveToBookmark is not possible when we are only forward");
422 else
423 SAL_WARN("dbaccess", "Bookmark is not valid");
424 throwFunctionSequenceException(*m_pMySelf);
427 checkCache();
429 bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
430 if ( bRet )
432 // check if we are inserting a row
433 bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
435 ORowSetNotifier aNotifier( this );
436 // this will call cancelRowModification on the cache if necessary
438 ORowSetRow aOldValues = getOldRow(bWasNew);
440 bRet = m_pCache->moveToBookmark(bookmark);
441 doCancelModification( );
442 if(bRet)
444 // notification order
445 // - column values
446 // - cursorMoved
447 setCurrentRow( true, true, aOldValues, aGuard );
449 else
451 movementFailed();
454 // - IsModified
455 // - IsNew
456 aNotifier.fire( );
458 SAL_INFO("dbaccess", "ORowSetBase::moveToBookmark(Any) = " << bRet << " Clone = " << m_bClone);
459 return bRet;
462 sal_Bool SAL_CALL ORowSetBase::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows )
464 SAL_INFO("dbaccess", "ORowSetBase::moveRelativeToBookmark(Any," << rows << ") Clone = " << m_bClone);
465 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
467 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
469 checkPositioningAllowed();
471 bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
472 if ( bRet )
474 // check if we are inserting a row
475 bool bWasNew = m_pCache->m_bNew || rowDeleted();
477 ORowSetNotifier aNotifier( this );
478 // this will call cancelRowModification on the cache if necessary
480 ORowSetRow aOldValues = getOldRow(bWasNew);
482 bRet = m_pCache->moveRelativeToBookmark(bookmark,rows);
483 doCancelModification( );
484 if(bRet)
486 // notification order
487 // - column values
488 // - cursorMoved
489 setCurrentRow( true, true, aOldValues, aGuard );
491 else
492 movementFailed();
494 // - IsModified
495 // - IsNew
496 aNotifier.fire( );
498 // RowCount/IsRowCountFinal
499 fireRowcount();
501 SAL_INFO("dbaccess", "ORowSetBase::moveRelativeToBookmark(Any," << rows << ") = " << bRet << " Clone = " << m_bClone);
502 return bRet;
505 sal_Int32 SAL_CALL ORowSetBase::compareBookmarks( const Any& _first, const Any& _second )
507 ::osl::MutexGuard aGuard( *m_pMutex );
508 checkCache();
509 return m_pCache->compareBookmarks(_first,_second);
512 sal_Bool SAL_CALL ORowSetBase::hasOrderedBookmarks( )
514 ::osl::MutexGuard aGuard( *m_pMutex );
515 checkCache();
516 return m_pCache->hasOrderedBookmarks();
519 sal_Int32 SAL_CALL ORowSetBase::hashBookmark( const Any& bookmark )
521 ::osl::MutexGuard aGuard( *m_pMutex );
522 checkCache();
523 return m_pCache->hashBookmark(bookmark);
526 // XResultSetMetaDataSupplier
527 Reference< XResultSetMetaData > SAL_CALL ORowSetBase::getMetaData( )
529 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
531 Reference< XResultSetMetaData > xMeta;
532 if(m_pCache)
533 xMeta = m_pCache->getMetaData();
535 return xMeta;
538 // XColumnLocate
539 sal_Int32 SAL_CALL ORowSetBase::findColumn( const OUString& columnName )
541 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
543 ::osl::MutexGuard aGuard( m_aColumnsMutex );
544 // it is possible to save some time here when we remember the names - position relation in a map
545 return m_pColumns ? m_pColumns->findColumn(columnName) : sal_Int32(0);
548 // css::sdbcx::XColumnsSupplier
549 Reference< XNameAccess > SAL_CALL ORowSetBase::getColumns( )
551 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
553 ::osl::MutexGuard aGuard( m_aColumnsMutex );
554 if(!m_pColumns)
556 if (!m_pEmptyCollection)
557 m_pEmptyCollection.reset( new OEmptyCollection(*m_pMySelf,m_aColumnsMutex) );
558 return m_pEmptyCollection.get();
561 return m_pColumns.get();
564 // XResultSet
565 sal_Bool SAL_CALL ORowSetBase::next( )
567 SAL_INFO("dbaccess", "ORowSetBase::next() Clone = " << m_bClone);
568 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
569 checkCache();
571 bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
572 if ( bRet )
574 // check if we are inserting a row
575 bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
577 ORowSetNotifier aNotifier( this );
578 // this will call cancelRowModification on the cache if necessary
580 ORowSetRow aOldValues = getOldRow(bWasNew);
582 positionCache( CursorMoveDirection::Forward );
583 bool bAfterLast = m_pCache->isAfterLast();
584 bRet = m_pCache->next();
585 doCancelModification( );
587 // if we were afterLast before next() then we still are,
588 // i.e. bAfterLast implies m_pCache->isAfterLast()
589 if (bAfterLast)
590 assert(m_pCache->isAfterLast());
591 // so the only way bAfterLast != m_pCache->isAfterLast()
592 // would be that we just arrived there,
593 if (bAfterLast != m_pCache->isAfterLast())
595 assert(!bAfterLast);
596 assert(m_pCache->isAfterLast());
598 // in which case we *did* move the cursor
599 if ( bRet || bAfterLast != m_pCache->isAfterLast() )
601 // notification order
602 // - column values
603 // - cursorMoved
604 setCurrentRow( true, true, aOldValues, aGuard );
605 OSL_ENSURE(!m_bBeforeFirst,"BeforeFirst is true. I don't know why?");
607 else
609 // moved after the last row
610 movementFailed();
611 OSL_ENSURE(m_bAfterLast,"AfterLast is false. I don't know why?");
614 // - IsModified
615 // - IsNew
616 aNotifier.fire();
618 // - RowCount/IsRowCountFinal
619 fireRowcount();
621 SAL_INFO("dbaccess", "ORowSetBase::next() = " << bRet << " Clone = " << m_bClone);
622 return bRet;
625 sal_Bool SAL_CALL ORowSetBase::isBeforeFirst( )
627 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
628 ::osl::MutexGuard aGuard( *m_pMutex );
629 checkCache();
631 SAL_INFO("dbaccess", "ORowSetBase::isBeforeFirst() = " << m_bBeforeFirst << " Clone = " << m_bClone);
633 return m_bBeforeFirst;
636 sal_Bool SAL_CALL ORowSetBase::isAfterLast( )
638 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
639 ::osl::MutexGuard aGuard( *m_pMutex );
640 checkCache();
641 SAL_INFO("dbaccess", "ORowSetBase::isAfterLast() = " << m_bAfterLast << " Clone = " << m_bClone);
643 return m_bAfterLast;
646 bool ORowSetBase::isOnFirst()
648 return isFirst();
651 sal_Bool SAL_CALL ORowSetBase::isFirst( )
653 SAL_INFO("dbaccess", "ORowSetBase::isFirst() Clone = " << m_bClone);
655 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
656 ::osl::MutexGuard aGuard( *m_pMutex );
657 checkCache();
659 if ( m_bBeforeFirst || m_bAfterLast )
660 return false;
662 if ( impl_rowDeleted() )
663 return ( m_nDeletedPosition == 1 );
665 positionCache( CursorMoveDirection::Current );
666 bool bIsFirst = m_pCache->isFirst();
668 SAL_INFO("dbaccess", "ORowSetBase::isFirst() = " << bIsFirst << " Clone = " << m_bClone);
669 return bIsFirst;
672 bool ORowSetBase::isOnLast()
674 return isLast();
677 sal_Bool SAL_CALL ORowSetBase::isLast( )
679 SAL_INFO("dbaccess", "ORowSetBase::isLast() Clone = " << m_bClone);
680 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
681 ::osl::MutexGuard aGuard( *m_pMutex );
682 checkCache();
684 if ( m_bBeforeFirst || m_bAfterLast )
685 return false;
687 if ( impl_rowDeleted() )
689 if ( !m_pCache->m_bRowCountFinal )
690 return false;
691 else
692 return ( m_nDeletedPosition == impl_getRowCount() );
695 positionCache( CursorMoveDirection::Current );
696 bool bIsLast = m_pCache->isLast();
698 SAL_INFO("dbaccess", "ORowSetBase::isLast() = " << bIsLast << " Clone = " << m_bClone);
699 return bIsLast;
702 void SAL_CALL ORowSetBase::beforeFirst( )
704 SAL_INFO("dbaccess", "ORowSetBase::beforeFirst() Clone = " << m_bClone);
705 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
706 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
708 checkPositioningAllowed();
710 // check if we are inserting a row
711 bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
713 if((bWasNew || !m_bBeforeFirst) && notifyAllListenersCursorBeforeMove(aGuard) )
715 ORowSetNotifier aNotifier( this );
716 // this will call cancelRowModification on the cache if necessary
718 if ( !m_bBeforeFirst )
720 ORowSetRow aOldValues = getOldRow(bWasNew);
721 m_pCache->beforeFirst();
722 doCancelModification( );
724 // notification order
725 // - column values
726 // - cursorMoved
727 setCurrentRow( true, true, aOldValues, aGuard );
729 // - IsModified
730 // - Isnew
731 aNotifier.fire();
733 // - RowCount/IsRowCountFinal
734 fireRowcount();
737 // to be done _after_ the notifications!
738 m_aOldRow->clearRow();
740 SAL_INFO("dbaccess", "ORowSetBase::beforeFirst() Clone = " << m_bClone);
743 void SAL_CALL ORowSetBase::afterLast( )
745 SAL_INFO("dbaccess", "ORowSetBase::afterLast() Clone = " << m_bClone);
746 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
748 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
749 checkPositioningAllowed();
751 bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
753 if((bWasNew || !m_bAfterLast) && notifyAllListenersCursorBeforeMove(aGuard) )
755 // check if we are inserting a row
756 ORowSetNotifier aNotifier( this );
757 // this will call cancelRowModification on the cache if necessary
759 if(!m_bAfterLast)
761 ORowSetRow aOldValues = getOldRow(bWasNew);
763 m_pCache->afterLast();
764 doCancelModification( );
766 // notification order
767 // - column values
768 // - cursorMoved
769 setCurrentRow( true, true, aOldValues, aGuard );
771 // - IsModified
772 // - Isnew
773 aNotifier.fire();
775 // - RowCount/IsRowCountFinal
776 fireRowcount();
779 SAL_INFO("dbaccess", "ORowSetBase::afterLast() Clone = " << m_bClone);
782 bool SAL_CALL ORowSetBase::move(std::function<bool(ORowSetBase *)> const & _aCheckFunctor,
783 std::function<bool(ORowSetCache *)> const & _aMovementFunctor)
785 SAL_INFO("dbaccess", "ORowSetBase::move() Clone = " << m_bClone);
786 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
787 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
788 checkPositioningAllowed();
790 bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
791 if( bRet )
793 // check if we are inserting a row
794 bool bWasNew = m_pCache->m_bNew || rowDeleted();
796 ORowSetNotifier aNotifier( this );
797 // this will call cancelRowModification on the cache if necessary
799 ORowSetRow aOldValues = getOldRow(bWasNew);
801 bool bMoved = ( bWasNew || !_aCheckFunctor(this) );
803 bRet = _aMovementFunctor(m_pCache.get());
804 doCancelModification( );
806 if ( bRet )
808 // notification order
809 // - column values
810 // - cursorMoved
811 setCurrentRow( bMoved, true, aOldValues, aGuard );
813 else
814 { // first goes wrong so there is no row
815 movementFailed();
818 // - IsModified
819 // - IsNew
820 aNotifier.fire();
822 // - RowCount/IsRowCountFinal
823 fireRowcount();
825 SAL_INFO("dbaccess", "ORowSetBase::move() = " << bRet << " Clone = " << m_bClone);
826 return bRet;
829 sal_Bool SAL_CALL ORowSetBase::first( )
831 SAL_INFO("dbaccess", "ORowSetBase::first() Clone = " << m_bClone);
832 auto ioF_tmp = std::mem_fn(&ORowSetBase::isOnFirst);
833 auto F_tmp = std::mem_fn(&ORowSetCache::first);
834 return move(ioF_tmp,F_tmp);
837 sal_Bool SAL_CALL ORowSetBase::last( )
839 SAL_INFO("dbaccess", "ORowSetBase::last() Clone = " << m_bClone);
840 auto ioL_tmp = std::mem_fn(&ORowSetBase::isOnLast);
841 auto L_tmp = std::mem_fn(&ORowSetCache::last);
842 return move(ioL_tmp,L_tmp);
845 sal_Int32 SAL_CALL ORowSetBase::getRow( )
847 SAL_INFO("dbaccess", "ORowSetBase::getRow() Clone = " << m_bClone);
848 ::osl::MutexGuard aGuard( *m_pMutex );
850 checkCache();
851 return impl_getRow();
854 sal_Int32 ORowSetBase::impl_getRow()
856 sal_Int32 nPos = 0;
857 if ( m_bBeforeFirst )
858 nPos = 0;
859 else if ( m_bAfterLast )
860 nPos = impl_getRowCount() + 1;
861 else if ( impl_rowDeleted() )
862 nPos = m_nDeletedPosition;
863 else if ( !m_bClone && m_pCache->m_bNew )
864 nPos = 0;
865 else
867 positionCache( CursorMoveDirection::Current );
868 nPos = m_pCache->getRow();
870 SAL_INFO("dbaccess", "ORowSetBase::impl_getRow() = " << nPos << " Clone = " << m_bClone);
871 return nPos;
874 sal_Bool SAL_CALL ORowSetBase::absolute( sal_Int32 row )
876 SAL_INFO("dbaccess", "ORowSetBase::absolute(" << row << ") Clone = " << m_bClone);
877 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
878 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
879 checkPositioningAllowed();
881 bool bRet = ( row > 0 )
882 && notifyAllListenersCursorBeforeMove( aGuard );
883 if ( bRet )
885 // check if we are inserting a row
886 bool bWasNew = m_pCache->m_bNew || rowDeleted();
888 ORowSetNotifier aNotifier( this );
889 // this will call cancelRowModification on the cache if necessary
891 ORowSetRow aOldValues = getOldRow(bWasNew);
893 bRet = m_pCache->absolute(row);
894 doCancelModification( );
896 if(bRet)
898 // notification order
899 // - column values
900 // - cursorMoved
901 setCurrentRow( true, true, aOldValues, aGuard );
903 else
904 { // absolute movement goes wrong we stand left or right side of the rows
905 movementFailed();
908 // - IsModified
909 // - IsNew
910 aNotifier.fire();
912 // - RowCount/IsRowCountFinal
913 fireRowcount();
915 SAL_INFO("dbaccess", "ORowSetBase::absolute(" << row << ") = " << bRet << " Clone = " << m_bClone);
916 return bRet;
919 sal_Bool SAL_CALL ORowSetBase::relative( sal_Int32 rows )
921 SAL_INFO("dbaccess", "ORowSetBase::relative(" << rows << ") Clone = " << m_bClone);
922 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
924 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
926 if(!rows)
927 return true; // in this case do nothing
929 checkPositioningAllowed();
931 bool bRet =
932 ( ( !m_bAfterLast || rows <= 0 )
933 && ( !m_bBeforeFirst || rows >= 0 )
934 && notifyAllListenersCursorBeforeMove( aGuard )
937 if ( bRet )
939 // check if we are inserting a row
940 bool bWasNew = m_pCache->m_bNew || rowDeleted();
942 ORowSetNotifier aNotifier( this );
943 // this will call cancelRowModification on the cache if necessary
945 ORowSetRow aOldValues = getOldRow(bWasNew);
947 positionCache( rows > 0 ? CursorMoveDirection::Forward : CursorMoveDirection::Backward );
948 bRet = m_pCache->relative(rows);
949 doCancelModification( );
951 if(bRet)
953 // notification order
954 // - column values
955 // - cursorMoved
956 setCurrentRow( true, true, aOldValues, aGuard );
958 else
960 movementFailed();
963 // - IsModified
964 // - IsNew
965 aNotifier.fire();
967 // - RowCount/IsRowCountFinal
968 fireRowcount();
970 SAL_INFO("dbaccess", "ORowSetBase::relative(" << rows << ") = " << bRet << " Clone = " << m_bClone);
971 return bRet;
974 sal_Bool SAL_CALL ORowSetBase::previous( )
976 SAL_INFO("dbaccess", "ORowSetBase::previous() Clone = " << m_bClone);
977 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
978 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
980 checkPositioningAllowed();
982 bool bRet = !m_bBeforeFirst
983 && notifyAllListenersCursorBeforeMove(aGuard);
985 if ( bRet )
987 // check if we are inserting a row
988 bool bWasNew = m_pCache->m_bNew || rowDeleted();
990 ORowSetNotifier aNotifier( this );
991 // this will call cancelRowModification on the cache if necessary
993 ORowSetRow aOldValues = getOldRow(bWasNew);
995 positionCache( CursorMoveDirection::Backward );
996 bRet = m_pCache->previous();
997 doCancelModification( );
999 // if m_bBeforeFirst is false and bRet is false then we stood on the first row
1000 if(!m_bBeforeFirst || bRet)
1002 // notification order
1003 // - column values
1004 // - cursorMoved
1005 setCurrentRow( true, true, aOldValues, aGuard );
1007 else
1009 SAL_WARN("dbaccess", "ORowSetBase::previous: inconsistency!" );
1010 // we should never reach this place, as we should not get into this whole branch if m_bBeforeFirst
1011 // was |true| from the beginning
1012 movementFailed();
1015 // - IsModified
1016 // - IsNew
1017 aNotifier.fire();
1019 // - RowCount/IsRowCountFinal
1020 fireRowcount();
1022 SAL_INFO("dbaccess", "ORowSetBase::previous() = " << bRet << " Clone = " << m_bClone);
1023 return bRet;
1026 void ORowSetBase::setCurrentRow( bool _bMoved, bool _bDoNotify, const ORowSetRow& _rOldValues, ::osl::ResettableMutexGuard& _rGuard )
1028 SAL_INFO("dbaccess", "ORowSetBase::setCurrentRow() Clone = " << m_bClone);
1029 m_bBeforeFirst = m_pCache->isBeforeFirst();
1030 m_bAfterLast = m_pCache->isAfterLast();
1032 if(!(m_bBeforeFirst || m_bAfterLast))
1034 m_aBookmark = m_pCache->getBookmark();
1035 OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!");
1036 m_aCurrentRow = m_pCache->m_aMatrixIter;
1037 m_bIsInsertRow = false;
1038 OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is null!");
1039 OSL_ENSURE(!m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd(),"Position of matrix iterator isn't valid!");
1040 OSL_ENSURE(m_aCurrentRow->is(),"Currentrow isn't valid");
1041 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 nul after positionCache!");
1046 #if OSL_DEBUG_LEVEL > 0
1047 ORowSetRow rRow = *m_aCurrentRow;
1048 OSL_ENSURE(rRow.is() ,"Invalid size of vector!");
1049 #endif
1051 // notification order
1052 // - column values
1053 if ( _bDoNotify )
1054 firePropertyChange(_rOldValues);
1057 else
1059 m_aOldRow->clearRow();
1060 m_aCurrentRow = m_pCache->getEnd();
1061 m_aBookmark = Any();
1064 // TODO: can this be done before the notifications?
1065 if(!(m_bBeforeFirst || m_bAfterLast) && !m_aCurrentRow.isNull() && m_aCurrentRow->is() && m_aCurrentRow != m_pCache->getEnd())
1066 m_aOldRow->setRow(new ORowSetValueVector( *(*m_aCurrentRow) ));
1068 if ( _bMoved && _bDoNotify )
1069 // - cursorMoved
1070 notifyAllListenersCursorMoved( _rGuard );
1072 SAL_INFO("dbaccess", "ORowSetBase::setCurrentRow() Clone = " << m_bClone);
1075 void ORowSetBase::checkPositioningAllowed()
1077 if(!m_pCache || m_nResultSetType == ResultSetType::FORWARD_ONLY)
1078 throwFunctionSequenceException(*m_pMySelf);
1081 Reference< XInterface > ORowSetBase::getStatement()
1083 return nullptr;
1086 void SAL_CALL ORowSetBase::refreshRow( )
1088 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
1089 ::osl::MutexGuard aGuard( *m_pMutex );
1090 checkCache();
1091 if ( impl_rowDeleted() )
1092 throwSQLException( "The current row is deleted", StandardSQLState::INVALID_CURSOR_STATE, Reference< XRowSet >( this ) );
1094 if(!(m_bBeforeFirst || m_bAfterLast))
1096 bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
1097 ORowSetRow aOldValues = getOldRow(bWasNew);
1098 positionCache( CursorMoveDirection::Current );
1099 m_pCache->refreshRow();
1100 firePropertyChange(aOldValues);
1104 sal_Bool SAL_CALL ORowSetBase::rowUpdated( )
1106 ::osl::MutexGuard aGuard( *m_pMutex );
1107 checkCache();
1109 if ( impl_rowDeleted() )
1110 return false;
1112 return m_pCache->rowUpdated();
1115 sal_Bool SAL_CALL ORowSetBase::rowInserted( )
1117 ::osl::MutexGuard aGuard( *m_pMutex );
1119 checkCache();
1121 if ( impl_rowDeleted() )
1122 return false;
1124 return m_pCache->rowInserted();
1127 sal_Bool SAL_CALL ORowSetBase::rowDeleted( )
1129 ::osl::MutexGuard aGuard( *m_pMutex );
1130 checkCache();
1131 return impl_rowDeleted();
1134 bool ORowSetBase::impl_rowDeleted( )
1136 return !m_aBookmark.hasValue() && !m_bBeforeFirst && !m_bAfterLast;
1139 // XWarningsSupplier
1140 Any SAL_CALL ORowSetBase::getWarnings( )
1142 ::osl::MutexGuard aGuard( *m_pMutex );
1144 if ( m_pCache )
1146 Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY );
1147 if ( xWarnings.is() )
1148 return xWarnings->getWarnings();
1151 return Any();
1154 void SAL_CALL ORowSetBase::clearWarnings( )
1156 ::osl::MutexGuard aGuard( *m_pMutex );
1158 if ( m_pCache )
1160 Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY );
1161 if ( xWarnings.is() )
1162 xWarnings->clearWarnings();
1166 void ORowSetBase::firePropertyChange(const ORowSetRow& _rOldRow)
1168 if (!isPropertyChangeNotificationEnabled())
1169 return;
1171 SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange" );
1172 SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange() Clone = " << m_bClone);
1173 OSL_ENSURE(m_pColumns,"Columns can not be NULL here!");
1174 sal_Int32 i=0;
1175 for (auto const& dataColumn : m_aDataColumns)
1179 dataColumn->fireValueChange(_rOldRow.is() ? (*_rOldRow)[i+1] : ::connectivity::ORowSetValue());
1181 catch (const Exception&)
1183 TOOLS_WARN_EXCEPTION("dbaccess", "firePropertyChange: Exception on column " << i);
1185 ++i;
1187 SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange() Clone = " << m_bClone);
1190 void ORowSetBase::firePropertyChange(sal_Int32 _nPos,const ::connectivity::ORowSetValue& _rOldValue)
1192 OSL_ENSURE(_nPos < static_cast<sal_Int32>(m_aDataColumns.size()),"nPos is invalid!");
1193 m_aDataColumns[_nPos]->fireValueChange(_rOldValue);
1196 void ORowSetBase::fireRowcount()
1200 bool ORowSetBase::notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& /*_rGuard*/)
1202 return true;
1205 void ORowSetBase::notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& /*_rGuard*/)
1209 bool ORowSetBase::isPropertyChangeNotificationEnabled() const
1211 return true;
1214 void ORowSetBase::fireProperty( sal_Int32 _nProperty, bool _bNew, bool _bOld )
1216 Any aNew( _bNew );
1217 Any aOld( _bOld );
1218 fire( &_nProperty, &aNew, &aOld, 1, false );
1221 void ORowSetBase::positionCache( CursorMoveDirection _ePrepareForDirection )
1223 SAL_INFO("dbaccess", "ORowSetBase::positionCache() Clone = " << m_bClone);
1225 bool bSuccess = false;
1226 if ( m_aBookmark.hasValue() )
1228 if (_ePrepareForDirection == CursorMoveDirection::CurrentRefresh ||
1229 (m_pCache->isAfterLast() != bool(isAfterLast())) || ( m_pCache->isBeforeFirst() != bool(isBeforeFirst()) ) ||
1230 m_pCache->compareBookmarks( m_aBookmark, m_pCache->getBookmark() ) != CompareBookmark::EQUAL )
1231 bSuccess = m_pCache->moveToBookmark( m_aBookmark );
1232 else
1233 bSuccess = true;
1235 else
1237 if ( m_bBeforeFirst )
1239 m_pCache->beforeFirst();
1240 bSuccess = true;
1242 else if ( m_bAfterLast )
1244 m_pCache->afterLast();
1245 bSuccess = true;
1247 else
1249 OSL_ENSURE( m_nDeletedPosition >= 1, "ORowSetBase::positionCache: no bookmark, and no valid 'deleted position'!" );
1250 switch ( _ePrepareForDirection )
1252 case CursorMoveDirection::Forward:
1253 if ( m_nDeletedPosition > 1 )
1254 bSuccess = m_pCache->absolute( m_nDeletedPosition - 1 );
1255 else
1257 m_pCache->beforeFirst();
1258 bSuccess = true;
1260 break;
1262 case CursorMoveDirection::Backward:
1263 if ( m_pCache->m_bRowCountFinal && ( m_nDeletedPosition == impl_getRowCount() ) )
1265 m_pCache->afterLast();
1266 bSuccess = true;
1268 else
1269 bSuccess = m_pCache->absolute( m_nDeletedPosition );
1270 break;
1272 case CursorMoveDirection::Current:
1273 case CursorMoveDirection::CurrentRefresh:
1274 bSuccess = false; // will be asserted below
1275 break;
1279 OSL_ENSURE( bSuccess, "ORowSetBase::positionCache: failed!" );
1281 SAL_INFO("dbaccess", "ORowSetBase::positionCache() Clone = " << m_bClone);
1284 void ORowSetBase::checkCache()
1286 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
1287 if(!m_pCache)
1288 throwFunctionSequenceException(*m_pMySelf);
1291 void ORowSetBase::movementFailed()
1293 SAL_INFO("dbaccess", "ORowSetBase::movementFailed() Clone = " << m_bClone);
1294 m_aOldRow->clearRow();
1295 m_aCurrentRow = m_pCache->getEnd();
1296 m_bBeforeFirst = m_pCache->isBeforeFirst();
1297 m_bAfterLast = m_pCache->isAfterLast();
1298 m_aBookmark = Any();
1299 OSL_ENSURE(m_bBeforeFirst || m_bAfterLast,"BeforeFirst or AfterLast is wrong!");
1300 SAL_INFO("dbaccess", "ORowSetBase::movementFailed() Clone = " << m_bClone);
1303 ORowSetRow ORowSetBase::getOldRow(bool _bWasNew)
1305 OSL_ENSURE(m_aOldRow.is(),"RowSetRowHElper isn't valid!");
1306 ORowSetRow aOldValues;
1307 if ( !_bWasNew && m_aOldRow->getRow().is() )
1308 aOldValues = new ORowSetValueVector( *(m_aOldRow->getRow())); // remember the old values
1309 return aOldValues;
1312 void ORowSetBase::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const
1314 _rDefault.clear();
1317 void ORowSetBase::onDeleteRow( const Any& _rBookmark )
1319 if ( rowDeleted() )
1320 // not interested in
1321 return;
1323 ::osl::MutexGuard aGuard( *m_pMutex );
1324 //OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::onDeleteRow: Bookmark isn't valid!" );
1325 if ( compareBookmarks( _rBookmark, m_aBookmark ) == CompareBookmark::EQUAL )
1327 positionCache( CursorMoveDirection::Current );
1328 m_nDeletedPosition = m_pCache->getRow();
1332 void ORowSetBase::onDeletedRow( const Any& _rBookmark, sal_Int32 _nPos )
1334 if ( rowDeleted() )
1336 // if we're a clone, and on a deleted row, and the main RowSet deleted another
1337 // row (only the main RowSet can, clones can't), which is *before* our
1338 // deleted position, then we have to adjust this position
1339 if ( m_bClone && ( _nPos < m_nDeletedPosition ) )
1340 --m_nDeletedPosition;
1341 return;
1344 ::osl::MutexGuard aGuard( *m_pMutex );
1345 if ( compareBookmarks( _rBookmark, m_aBookmark ) == CompareBookmark::EQUAL )
1347 m_aOldRow->clearRow();
1348 m_aCurrentRow = m_pCache->getEnd();
1349 m_aBookmark = Any();
1353 sal_Int32 ORowSetBase::impl_getRowCount() const
1355 sal_Int32 nRowCount( m_pCache->m_nRowCount );
1356 if ( const_cast< ORowSetBase* >( this )->rowDeleted() && !m_pCache->m_bNew )
1357 ++nRowCount;
1358 return nRowCount;
1362 ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet )
1363 :m_pRowSet( _pRowSet )
1364 ,m_bWasNew( false )
1365 ,m_bWasModified( false )
1368 OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This will crash." );
1370 // remember the "inserted" and "modified" state for later firing
1371 m_bWasNew = m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() );
1372 m_bWasModified = m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() );
1374 // if the row set is on the insert row, then we need to cancel this
1375 if ( m_pRowSet->isModification( ORowSetBase::GrantNotifierAccess() ) )
1376 m_pRowSet->doCancelModification( ORowSetBase::GrantNotifierAccess() );
1379 ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet, ORowSetValueVector::Vector&& i_aRow )
1380 :m_pRowSet( _pRowSet )
1381 ,m_bWasNew( false )
1382 ,m_bWasModified( false )
1384 OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This will crash." );
1385 aRow = std::move(i_aRow); // yes, create a copy to store the old values
1388 ORowSetNotifier::~ORowSetNotifier( )
1392 void ORowSetNotifier::fire()
1394 // we're not interested in firing changes FALSE->TRUE, only TRUE->FALSE.
1395 // (the former would be quite pathological, e.g. after a failed movement)
1397 if ( m_bWasModified
1398 && ( m_bWasModified != m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() ) )
1400 m_pRowSet->fireProperty( PROPERTY_ID_ISMODIFIED, false, true, ORowSetBase::GrantNotifierAccess() );
1402 if ( m_bWasNew
1403 && ( m_bWasNew != m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() ) )
1405 m_pRowSet->fireProperty( PROPERTY_ID_ISNEW, false, true, ORowSetBase::GrantNotifierAccess() );
1408 std::vector<sal_Int32>& ORowSetNotifier::getChangedColumns()
1410 return aChangedColumns;
1413 void ORowSetNotifier::firePropertyChange()
1415 for (auto const& changedColumn : aChangedColumns)
1417 m_pRowSet->firePropertyChange(changedColumn-1, aRow[changedColumn-1], ORowSetBase::GrantNotifierAccess());
1419 if ( !aChangedColumns.empty() )
1420 m_pRowSet->fireProperty(PROPERTY_ID_ISMODIFIED,true,false, ORowSetBase::GrantNotifierAccess());
1423 } // namespace dbaccess
1425 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */