cid#1640468 Dereference after null check
[LibreOffice.git] / dbaccess / source / core / api / RowSetBase.cxx
blobd2811d8af56480f05adb24f1754d0859986571bc
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*>(sal_uIntPtr(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( u"XRow::getRef"_ustr, *m_pMySelf );
377 Reference< XBlob > SAL_CALL ORowSetBase::getBlob( sal_Int32 columnIndex )
379 return Reference< XBlob >(getValue(columnIndex).makeAny(),UNO_QUERY);
382 Reference< XClob > SAL_CALL ORowSetBase::getClob( sal_Int32 columnIndex )
384 return Reference< XClob >(getValue(columnIndex).makeAny(),UNO_QUERY);
387 Reference< XArray > SAL_CALL ORowSetBase::getArray( sal_Int32 /*columnIndex*/ )
389 ::dbtools::throwFeatureNotImplementedSQLException( u"XRow::getArray"_ustr, *m_pMySelf );
392 // css::sdbcx::XRowLocate
393 Any SAL_CALL ORowSetBase::getBookmark( )
395 SAL_INFO("dbaccess", "ORowSetBase::getBookmark() Clone = " << m_bClone);
396 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
397 ::osl::MutexGuard aGuard( *m_pMutex );
398 checkCache();
400 if ( m_bBeforeFirst || m_bAfterLast )
401 ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_BOOKMARK_BEFORE_OR_AFTER ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );
403 if ( impl_rowDeleted() )
404 ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_BOOKMARK_DELETED ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );
406 OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::getBookmark: bookmark has no value!" );
407 return m_aBookmark;
410 sal_Bool SAL_CALL ORowSetBase::moveToBookmark( const Any& bookmark )
412 SAL_INFO("dbaccess", "ORowSetBase::moveToBookmark(Any) Clone = " << m_bClone);
413 OSL_ENSURE(bookmark.hasValue(),"ORowSetBase::moveToBookmark bookmark has no value!");
414 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
416 if(!bookmark.hasValue() || m_nResultSetType == ResultSetType::FORWARD_ONLY)
418 if(bookmark.hasValue())
419 SAL_WARN("dbaccess", "MoveToBookmark is not possible when we are only forward");
420 else
421 SAL_WARN("dbaccess", "Bookmark is not valid");
422 throwFunctionSequenceException(*m_pMySelf);
425 checkCache();
427 bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
428 if ( bRet )
430 // check if we are inserting a row
431 bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
433 ORowSetNotifier aNotifier( this );
434 // this will call cancelRowModification on the cache if necessary
436 ORowSetRow aOldValues = getOldRow(bWasNew);
438 bRet = m_pCache->moveToBookmark(bookmark);
439 doCancelModification( );
440 if(bRet)
442 // notification order
443 // - column values
444 // - cursorMoved
445 setCurrentRow( true, true, aOldValues, aGuard );
447 else
449 movementFailed();
452 // - IsModified
453 // - IsNew
454 aNotifier.fire( );
456 SAL_INFO("dbaccess", "ORowSetBase::moveToBookmark(Any) = " << bRet << " Clone = " << m_bClone);
457 return bRet;
460 sal_Bool SAL_CALL ORowSetBase::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows )
462 SAL_INFO("dbaccess", "ORowSetBase::moveRelativeToBookmark(Any," << rows << ") Clone = " << m_bClone);
463 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
465 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
467 checkPositioningAllowed();
469 bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
470 if ( bRet )
472 // check if we are inserting a row
473 bool bWasNew = m_pCache->m_bNew || rowDeleted();
475 ORowSetNotifier aNotifier( this );
476 // this will call cancelRowModification on the cache if necessary
478 ORowSetRow aOldValues = getOldRow(bWasNew);
480 bRet = m_pCache->moveRelativeToBookmark(bookmark,rows);
481 doCancelModification( );
482 if(bRet)
484 // notification order
485 // - column values
486 // - cursorMoved
487 setCurrentRow( true, true, aOldValues, aGuard );
489 else
490 movementFailed();
492 // - IsModified
493 // - IsNew
494 aNotifier.fire( );
496 // RowCount/IsRowCountFinal
497 fireRowcount();
499 SAL_INFO("dbaccess", "ORowSetBase::moveRelativeToBookmark(Any," << rows << ") = " << bRet << " Clone = " << m_bClone);
500 return bRet;
503 sal_Int32 SAL_CALL ORowSetBase::compareBookmarks( const Any& _first, const Any& _second )
505 ::osl::MutexGuard aGuard( *m_pMutex );
506 checkCache();
507 return m_pCache->compareBookmarks(_first,_second);
510 sal_Bool SAL_CALL ORowSetBase::hasOrderedBookmarks( )
512 ::osl::MutexGuard aGuard( *m_pMutex );
513 checkCache();
514 return m_pCache->hasOrderedBookmarks();
517 sal_Int32 SAL_CALL ORowSetBase::hashBookmark( const Any& bookmark )
519 ::osl::MutexGuard aGuard( *m_pMutex );
520 checkCache();
521 return m_pCache->hashBookmark(bookmark);
524 // XResultSetMetaDataSupplier
525 Reference< XResultSetMetaData > SAL_CALL ORowSetBase::getMetaData( )
527 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
529 Reference< XResultSetMetaData > xMeta;
530 if(m_pCache)
531 xMeta = m_pCache->getMetaData();
533 return xMeta;
536 // XColumnLocate
537 sal_Int32 SAL_CALL ORowSetBase::findColumn( const OUString& columnName )
539 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
541 ::osl::MutexGuard aGuard( m_aColumnsMutex );
542 // it is possible to save some time here when we remember the names - position relation in a map
543 return m_pColumns ? m_pColumns->findColumn(columnName) : sal_Int32(0);
546 // css::sdbcx::XColumnsSupplier
547 Reference< XNameAccess > SAL_CALL ORowSetBase::getColumns( )
549 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
551 ::osl::MutexGuard aGuard( m_aColumnsMutex );
552 if(!m_pColumns)
554 if (!m_pEmptyCollection)
555 m_pEmptyCollection.reset( new OEmptyCollection(*m_pMySelf,m_aColumnsMutex) );
556 return m_pEmptyCollection.get();
559 return m_pColumns.get();
562 // XResultSet
563 sal_Bool SAL_CALL ORowSetBase::next( )
565 SAL_INFO("dbaccess", "ORowSetBase::next() Clone = " << m_bClone);
566 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
567 checkCache();
569 bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
570 if ( bRet )
572 // check if we are inserting a row
573 bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
575 ORowSetNotifier aNotifier( this );
576 // this will call cancelRowModification on the cache if necessary
578 ORowSetRow aOldValues = getOldRow(bWasNew);
580 positionCache( CursorMoveDirection::Forward );
581 bool bAfterLast = m_pCache->isAfterLast();
582 bRet = m_pCache->next();
583 doCancelModification( );
585 // if we were afterLast before next() then we still are,
586 // i.e. bAfterLast implies m_pCache->isAfterLast()
587 if (bAfterLast)
588 assert(m_pCache->isAfterLast());
589 // so the only way bAfterLast != m_pCache->isAfterLast()
590 // would be that we just arrived there,
591 if (bAfterLast != m_pCache->isAfterLast())
593 assert(!bAfterLast);
594 assert(m_pCache->isAfterLast());
596 // in which case we *did* move the cursor
597 if ( bRet || bAfterLast != m_pCache->isAfterLast() )
599 // notification order
600 // - column values
601 // - cursorMoved
602 setCurrentRow( true, true, aOldValues, aGuard );
603 OSL_ENSURE(!m_bBeforeFirst,"BeforeFirst is true. I don't know why?");
605 else
607 // moved after the last row
608 movementFailed();
609 OSL_ENSURE(m_bAfterLast,"AfterLast is false. I don't know why?");
612 // - IsModified
613 // - IsNew
614 aNotifier.fire();
616 // - RowCount/IsRowCountFinal
617 fireRowcount();
619 SAL_INFO("dbaccess", "ORowSetBase::next() = " << bRet << " Clone = " << m_bClone);
620 return bRet;
623 sal_Bool SAL_CALL ORowSetBase::isBeforeFirst( )
625 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
626 ::osl::MutexGuard aGuard( *m_pMutex );
627 checkCache();
629 SAL_INFO("dbaccess", "ORowSetBase::isBeforeFirst() = " << m_bBeforeFirst << " Clone = " << m_bClone);
631 return m_bBeforeFirst;
634 sal_Bool SAL_CALL ORowSetBase::isAfterLast( )
636 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
637 ::osl::MutexGuard aGuard( *m_pMutex );
638 checkCache();
639 SAL_INFO("dbaccess", "ORowSetBase::isAfterLast() = " << m_bAfterLast << " Clone = " << m_bClone);
641 return m_bAfterLast;
644 bool ORowSetBase::isOnFirst()
646 return isFirst();
649 sal_Bool SAL_CALL ORowSetBase::isFirst( )
651 SAL_INFO("dbaccess", "ORowSetBase::isFirst() Clone = " << m_bClone);
653 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
654 ::osl::MutexGuard aGuard( *m_pMutex );
655 checkCache();
657 if ( m_bBeforeFirst || m_bAfterLast )
658 return false;
660 if ( impl_rowDeleted() )
661 return ( m_nDeletedPosition == 1 );
663 positionCache( CursorMoveDirection::Current );
664 bool bIsFirst = m_pCache->isFirst();
666 SAL_INFO("dbaccess", "ORowSetBase::isFirst() = " << bIsFirst << " Clone = " << m_bClone);
667 return bIsFirst;
670 bool ORowSetBase::isOnLast()
672 return isLast();
675 sal_Bool SAL_CALL ORowSetBase::isLast( )
677 SAL_INFO("dbaccess", "ORowSetBase::isLast() Clone = " << m_bClone);
678 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
679 ::osl::MutexGuard aGuard( *m_pMutex );
680 checkCache();
682 if ( m_bBeforeFirst || m_bAfterLast )
683 return false;
685 if ( impl_rowDeleted() )
687 if ( !m_pCache->m_bRowCountFinal )
688 return false;
689 else
690 return ( m_nDeletedPosition == impl_getRowCount() );
693 positionCache( CursorMoveDirection::Current );
694 bool bIsLast = m_pCache->isLast();
696 SAL_INFO("dbaccess", "ORowSetBase::isLast() = " << bIsLast << " Clone = " << m_bClone);
697 return bIsLast;
700 void SAL_CALL ORowSetBase::beforeFirst( )
702 SAL_INFO("dbaccess", "ORowSetBase::beforeFirst() Clone = " << m_bClone);
703 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
704 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
706 checkPositioningAllowed();
708 // check if we are inserting a row
709 bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
711 if((bWasNew || !m_bBeforeFirst) && notifyAllListenersCursorBeforeMove(aGuard) )
713 ORowSetNotifier aNotifier( this );
714 // this will call cancelRowModification on the cache if necessary
716 if ( !m_bBeforeFirst )
718 ORowSetRow aOldValues = getOldRow(bWasNew);
719 m_pCache->beforeFirst();
720 doCancelModification( );
722 // notification order
723 // - column values
724 // - cursorMoved
725 setCurrentRow( true, true, aOldValues, aGuard );
727 // - IsModified
728 // - Isnew
729 aNotifier.fire();
731 // - RowCount/IsRowCountFinal
732 fireRowcount();
735 // to be done _after_ the notifications!
736 m_aOldRow->clearRow();
738 SAL_INFO("dbaccess", "ORowSetBase::beforeFirst() Clone = " << m_bClone);
741 void SAL_CALL ORowSetBase::afterLast( )
743 SAL_INFO("dbaccess", "ORowSetBase::afterLast() Clone = " << m_bClone);
744 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
746 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
747 checkPositioningAllowed();
749 bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
751 if((bWasNew || !m_bAfterLast) && notifyAllListenersCursorBeforeMove(aGuard) )
753 // check if we are inserting a row
754 ORowSetNotifier aNotifier( this );
755 // this will call cancelRowModification on the cache if necessary
757 if(!m_bAfterLast)
759 ORowSetRow aOldValues = getOldRow(bWasNew);
761 m_pCache->afterLast();
762 doCancelModification( );
764 // notification order
765 // - column values
766 // - cursorMoved
767 setCurrentRow( true, true, aOldValues, aGuard );
769 // - IsModified
770 // - Isnew
771 aNotifier.fire();
773 // - RowCount/IsRowCountFinal
774 fireRowcount();
777 SAL_INFO("dbaccess", "ORowSetBase::afterLast() Clone = " << m_bClone);
780 bool SAL_CALL ORowSetBase::move(std::function<bool(ORowSetBase *)> const & _aCheckFunctor,
781 std::function<bool(ORowSetCache *)> const & _aMovementFunctor)
783 SAL_INFO("dbaccess", "ORowSetBase::move() Clone = " << m_bClone);
784 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
785 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
786 checkPositioningAllowed();
788 bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
789 if( bRet )
791 // check if we are inserting a row
792 bool bWasNew = m_pCache->m_bNew || rowDeleted();
794 ORowSetNotifier aNotifier( this );
795 // this will call cancelRowModification on the cache if necessary
797 ORowSetRow aOldValues = getOldRow(bWasNew);
799 bool bMoved = ( bWasNew || !_aCheckFunctor(this) );
801 bRet = _aMovementFunctor(m_pCache.get());
802 doCancelModification( );
804 if ( bRet )
806 // notification order
807 // - column values
808 // - cursorMoved
809 setCurrentRow( bMoved, true, aOldValues, aGuard );
811 else
812 { // first goes wrong so there is no row
813 movementFailed();
816 // - IsModified
817 // - IsNew
818 aNotifier.fire();
820 // - RowCount/IsRowCountFinal
821 fireRowcount();
823 SAL_INFO("dbaccess", "ORowSetBase::move() = " << bRet << " Clone = " << m_bClone);
824 return bRet;
827 sal_Bool SAL_CALL ORowSetBase::first( )
829 SAL_INFO("dbaccess", "ORowSetBase::first() Clone = " << m_bClone);
830 auto ioF_tmp = std::mem_fn(&ORowSetBase::isOnFirst);
831 auto F_tmp = std::mem_fn(&ORowSetCache::first);
832 return move(ioF_tmp,F_tmp);
835 sal_Bool SAL_CALL ORowSetBase::last( )
837 SAL_INFO("dbaccess", "ORowSetBase::last() Clone = " << m_bClone);
838 auto ioL_tmp = std::mem_fn(&ORowSetBase::isOnLast);
839 auto L_tmp = std::mem_fn(&ORowSetCache::last);
840 return move(ioL_tmp,L_tmp);
843 sal_Int32 SAL_CALL ORowSetBase::getRow( )
845 SAL_INFO("dbaccess", "ORowSetBase::getRow() Clone = " << m_bClone);
846 ::osl::MutexGuard aGuard( *m_pMutex );
848 checkCache();
849 return impl_getRow();
852 sal_Int32 ORowSetBase::impl_getRow()
854 sal_Int32 nPos = 0;
855 if ( m_bBeforeFirst )
856 nPos = 0;
857 else if ( m_bAfterLast )
858 nPos = impl_getRowCount() + 1;
859 else if ( impl_rowDeleted() )
860 nPos = m_nDeletedPosition;
861 else if ( !m_bClone && m_pCache->m_bNew )
862 nPos = 0;
863 else
865 positionCache( CursorMoveDirection::Current );
866 nPos = m_pCache->getRow();
868 SAL_INFO("dbaccess", "ORowSetBase::impl_getRow() = " << nPos << " Clone = " << m_bClone);
869 return nPos;
872 sal_Bool SAL_CALL ORowSetBase::absolute( sal_Int32 row )
874 SAL_INFO("dbaccess", "ORowSetBase::absolute(" << row << ") Clone = " << m_bClone);
875 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
876 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
877 checkPositioningAllowed();
879 bool bRet = ( row > 0 )
880 && notifyAllListenersCursorBeforeMove( aGuard );
881 if ( bRet )
883 // check if we are inserting a row
884 bool bWasNew = m_pCache->m_bNew || rowDeleted();
886 ORowSetNotifier aNotifier( this );
887 // this will call cancelRowModification on the cache if necessary
889 ORowSetRow aOldValues = getOldRow(bWasNew);
891 bRet = m_pCache->absolute(row);
892 doCancelModification( );
894 if(bRet)
896 // notification order
897 // - column values
898 // - cursorMoved
899 setCurrentRow( true, true, aOldValues, aGuard );
901 else
902 { // absolute movement goes wrong we stand left or right side of the rows
903 movementFailed();
906 // - IsModified
907 // - IsNew
908 aNotifier.fire();
910 // - RowCount/IsRowCountFinal
911 fireRowcount();
913 SAL_INFO("dbaccess", "ORowSetBase::absolute(" << row << ") = " << bRet << " Clone = " << m_bClone);
914 return bRet;
917 sal_Bool SAL_CALL ORowSetBase::relative( sal_Int32 rows )
919 SAL_INFO("dbaccess", "ORowSetBase::relative(" << rows << ") Clone = " << m_bClone);
920 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
922 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
924 if(!rows)
925 return true; // in this case do nothing
927 checkPositioningAllowed();
929 bool bRet =
930 ( ( !m_bAfterLast || rows <= 0 )
931 && ( !m_bBeforeFirst || rows >= 0 )
932 && notifyAllListenersCursorBeforeMove( aGuard )
935 if ( bRet )
937 // check if we are inserting a row
938 bool bWasNew = m_pCache->m_bNew || rowDeleted();
940 ORowSetNotifier aNotifier( this );
941 // this will call cancelRowModification on the cache if necessary
943 ORowSetRow aOldValues = getOldRow(bWasNew);
945 positionCache( rows > 0 ? CursorMoveDirection::Forward : CursorMoveDirection::Backward );
946 bRet = m_pCache->relative(rows);
947 doCancelModification( );
949 if(bRet)
951 // notification order
952 // - column values
953 // - cursorMoved
954 setCurrentRow( true, true, aOldValues, aGuard );
956 else
958 movementFailed();
961 // - IsModified
962 // - IsNew
963 aNotifier.fire();
965 // - RowCount/IsRowCountFinal
966 fireRowcount();
968 SAL_INFO("dbaccess", "ORowSetBase::relative(" << rows << ") = " << bRet << " Clone = " << m_bClone);
969 return bRet;
972 sal_Bool SAL_CALL ORowSetBase::previous( )
974 SAL_INFO("dbaccess", "ORowSetBase::previous() Clone = " << m_bClone);
975 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
976 ::osl::ResettableMutexGuard aGuard( *m_pMutex );
978 checkPositioningAllowed();
980 bool bRet = !m_bBeforeFirst
981 && notifyAllListenersCursorBeforeMove(aGuard);
983 if ( bRet )
985 // check if we are inserting a row
986 bool bWasNew = m_pCache->m_bNew || rowDeleted();
988 ORowSetNotifier aNotifier( this );
989 // this will call cancelRowModification on the cache if necessary
991 ORowSetRow aOldValues = getOldRow(bWasNew);
993 positionCache( CursorMoveDirection::Backward );
994 bRet = m_pCache->previous();
995 doCancelModification( );
997 // if m_bBeforeFirst is false and bRet is false then we stood on the first row
998 if(!m_bBeforeFirst || bRet)
1000 // notification order
1001 // - column values
1002 // - cursorMoved
1003 setCurrentRow( true, true, aOldValues, aGuard );
1005 else
1007 SAL_WARN("dbaccess", "ORowSetBase::previous: inconsistency!" );
1008 // we should never reach this place, as we should not get into this whole branch if m_bBeforeFirst
1009 // was |true| from the beginning
1010 movementFailed();
1013 // - IsModified
1014 // - IsNew
1015 aNotifier.fire();
1017 // - RowCount/IsRowCountFinal
1018 fireRowcount();
1020 SAL_INFO("dbaccess", "ORowSetBase::previous() = " << bRet << " Clone = " << m_bClone);
1021 return bRet;
1024 void ORowSetBase::setCurrentRow( bool _bMoved, bool _bDoNotify, const ORowSetRow& _rOldValues, ::osl::ResettableMutexGuard& _rGuard )
1026 SAL_INFO("dbaccess", "ORowSetBase::setCurrentRow() Clone = " << m_bClone);
1027 m_bBeforeFirst = m_pCache->isBeforeFirst();
1028 m_bAfterLast = m_pCache->isAfterLast();
1030 if(!(m_bBeforeFirst || m_bAfterLast))
1032 m_aBookmark = m_pCache->getBookmark();
1033 OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!");
1034 m_aCurrentRow = m_pCache->m_aMatrixIter;
1035 m_bIsInsertRow = false;
1036 OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is null!");
1037 OSL_ENSURE(!m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd(),"Position of matrix iterator isn't valid!");
1038 OSL_ENSURE(m_aCurrentRow->is(),"Currentrow isn't valid");
1039 OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!");
1041 m_aCurrentRow = m_pCache->m_aMatrixIter;
1042 m_bIsInsertRow = false;
1043 OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is nul after positionCache!");
1044 #if OSL_DEBUG_LEVEL > 0
1045 ORowSetRow rRow = *m_aCurrentRow;
1046 OSL_ENSURE(rRow.is() ,"Invalid size of vector!");
1047 #endif
1049 // notification order
1050 // - column values
1051 if ( _bDoNotify )
1052 firePropertyChange(_rOldValues);
1055 else
1057 m_aOldRow->clearRow();
1058 m_aCurrentRow = m_pCache->getEnd();
1059 m_aBookmark = Any();
1062 // TODO: can this be done before the notifications?
1063 if(!(m_bBeforeFirst || m_bAfterLast) && !m_aCurrentRow.isNull() && m_aCurrentRow->is() && m_aCurrentRow != m_pCache->getEnd())
1064 m_aOldRow->setRow(new ORowSetValueVector( *(*m_aCurrentRow) ));
1066 if ( _bMoved && _bDoNotify )
1067 // - cursorMoved
1068 notifyAllListenersCursorMoved( _rGuard );
1070 SAL_INFO("dbaccess", "ORowSetBase::setCurrentRow() Clone = " << m_bClone);
1073 void ORowSetBase::checkPositioningAllowed()
1075 if(!m_pCache || m_nResultSetType == ResultSetType::FORWARD_ONLY)
1076 throwFunctionSequenceException(*m_pMySelf);
1079 Reference< XInterface > ORowSetBase::getStatement()
1081 return nullptr;
1084 void SAL_CALL ORowSetBase::refreshRow( )
1086 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
1087 ::osl::MutexGuard aGuard( *m_pMutex );
1088 checkCache();
1089 if ( impl_rowDeleted() )
1090 throwSQLException( u"The current row is deleted"_ustr, StandardSQLState::INVALID_CURSOR_STATE, Reference< XRowSet >( this ) );
1092 if(!(m_bBeforeFirst || m_bAfterLast))
1094 bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
1095 ORowSetRow aOldValues = getOldRow(bWasNew);
1096 positionCache( CursorMoveDirection::Current );
1097 m_pCache->refreshRow();
1098 firePropertyChange(aOldValues);
1102 sal_Bool SAL_CALL ORowSetBase::rowUpdated( )
1104 ::osl::MutexGuard aGuard( *m_pMutex );
1105 checkCache();
1107 if ( impl_rowDeleted() )
1108 return false;
1110 return m_pCache->rowUpdated();
1113 sal_Bool SAL_CALL ORowSetBase::rowInserted( )
1115 ::osl::MutexGuard aGuard( *m_pMutex );
1117 checkCache();
1119 if ( impl_rowDeleted() )
1120 return false;
1122 return m_pCache->rowInserted();
1125 sal_Bool SAL_CALL ORowSetBase::rowDeleted( )
1127 ::osl::MutexGuard aGuard( *m_pMutex );
1128 checkCache();
1129 return impl_rowDeleted();
1132 bool ORowSetBase::impl_rowDeleted( )
1134 return !m_aBookmark.hasValue() && !m_bBeforeFirst && !m_bAfterLast;
1137 // XWarningsSupplier
1138 Any SAL_CALL ORowSetBase::getWarnings( )
1140 ::osl::MutexGuard aGuard( *m_pMutex );
1142 if ( m_pCache )
1144 Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY );
1145 if ( xWarnings.is() )
1146 return xWarnings->getWarnings();
1149 return Any();
1152 void SAL_CALL ORowSetBase::clearWarnings( )
1154 ::osl::MutexGuard aGuard( *m_pMutex );
1156 if ( m_pCache )
1158 Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY );
1159 if ( xWarnings.is() )
1160 xWarnings->clearWarnings();
1164 void ORowSetBase::firePropertyChange(const ORowSetRow& _rOldRow)
1166 if (!isPropertyChangeNotificationEnabled())
1167 return;
1169 SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange" );
1170 SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange() Clone = " << m_bClone);
1171 OSL_ENSURE(m_pColumns,"Columns can not be NULL here!");
1172 sal_Int32 i=0;
1173 for (auto const& dataColumn : m_aDataColumns)
1177 dataColumn->fireValueChange(_rOldRow.is() ? (*_rOldRow)[i+1] : ::connectivity::ORowSetValue());
1179 catch (const Exception&)
1181 TOOLS_WARN_EXCEPTION("dbaccess", "firePropertyChange: Exception on column " << i);
1183 ++i;
1185 SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange() Clone = " << m_bClone);
1188 void ORowSetBase::firePropertyChange(sal_Int32 _nPos,const ::connectivity::ORowSetValue& _rOldValue)
1190 OSL_ENSURE(_nPos < static_cast<sal_Int32>(m_aDataColumns.size()),"nPos is invalid!");
1191 m_aDataColumns[_nPos]->fireValueChange(_rOldValue);
1194 void ORowSetBase::fireRowcount()
1198 bool ORowSetBase::notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& /*_rGuard*/)
1200 return true;
1203 void ORowSetBase::notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& /*_rGuard*/)
1207 bool ORowSetBase::isPropertyChangeNotificationEnabled() const
1209 return true;
1212 void ORowSetBase::fireProperty( sal_Int32 _nProperty, bool _bNew, bool _bOld )
1214 Any aNew( _bNew );
1215 Any aOld( _bOld );
1216 fire( &_nProperty, &aNew, &aOld, 1, false );
1219 void ORowSetBase::positionCache( CursorMoveDirection _ePrepareForDirection )
1221 SAL_INFO("dbaccess", "ORowSetBase::positionCache() Clone = " << m_bClone);
1223 bool bSuccess = false;
1224 if ( m_aBookmark.hasValue() )
1226 if (_ePrepareForDirection == CursorMoveDirection::CurrentRefresh ||
1227 (m_pCache->isAfterLast() != bool(isAfterLast())) || ( m_pCache->isBeforeFirst() != bool(isBeforeFirst()) ) ||
1228 m_pCache->compareBookmarks( m_aBookmark, m_pCache->getBookmark() ) != CompareBookmark::EQUAL )
1229 bSuccess = m_pCache->moveToBookmark( m_aBookmark );
1230 else
1231 bSuccess = true;
1233 else
1235 if ( m_bBeforeFirst )
1237 m_pCache->beforeFirst();
1238 bSuccess = true;
1240 else if ( m_bAfterLast )
1242 m_pCache->afterLast();
1243 bSuccess = true;
1245 else
1247 OSL_ENSURE( m_nDeletedPosition >= 1, "ORowSetBase::positionCache: no bookmark, and no valid 'deleted position'!" );
1248 switch ( _ePrepareForDirection )
1250 case CursorMoveDirection::Forward:
1251 if ( m_nDeletedPosition > 1 )
1252 bSuccess = m_pCache->absolute( m_nDeletedPosition - 1 );
1253 else
1255 m_pCache->beforeFirst();
1256 bSuccess = true;
1258 break;
1260 case CursorMoveDirection::Backward:
1261 if ( m_pCache->m_bRowCountFinal && ( m_nDeletedPosition == impl_getRowCount() ) )
1263 m_pCache->afterLast();
1264 bSuccess = true;
1266 else
1267 bSuccess = m_pCache->absolute( m_nDeletedPosition );
1268 break;
1270 case CursorMoveDirection::Current:
1271 case CursorMoveDirection::CurrentRefresh:
1272 bSuccess = false; // will be asserted below
1273 break;
1277 OSL_ENSURE( bSuccess, "ORowSetBase::positionCache: failed!" );
1279 SAL_INFO("dbaccess", "ORowSetBase::positionCache() Clone = " << m_bClone);
1282 void ORowSetBase::checkCache()
1284 ::connectivity::checkDisposed(m_rBHelper.bDisposed);
1285 if(!m_pCache)
1286 throwFunctionSequenceException(*m_pMySelf);
1289 void ORowSetBase::movementFailed()
1291 SAL_INFO("dbaccess", "ORowSetBase::movementFailed() Clone = " << m_bClone);
1292 m_aOldRow->clearRow();
1293 m_aCurrentRow = m_pCache->getEnd();
1294 m_bBeforeFirst = m_pCache->isBeforeFirst();
1295 m_bAfterLast = m_pCache->isAfterLast();
1296 m_aBookmark = Any();
1297 OSL_ENSURE(m_bBeforeFirst || m_bAfterLast,"BeforeFirst or AfterLast is wrong!");
1298 SAL_INFO("dbaccess", "ORowSetBase::movementFailed() Clone = " << m_bClone);
1301 ORowSetRow ORowSetBase::getOldRow(bool _bWasNew)
1303 OSL_ENSURE(m_aOldRow.is(),"RowSetRowHElper isn't valid!");
1304 ORowSetRow aOldValues;
1305 if ( !_bWasNew && m_aOldRow->getRow().is() )
1306 aOldValues = new ORowSetValueVector( *(m_aOldRow->getRow())); // remember the old values
1307 return aOldValues;
1310 void ORowSetBase::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const
1312 _rDefault.clear();
1315 void ORowSetBase::onDeleteRow( const Any& _rBookmark )
1317 if ( rowDeleted() )
1318 // not interested in
1319 return;
1321 ::osl::MutexGuard aGuard( *m_pMutex );
1322 //OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::onDeleteRow: Bookmark isn't valid!" );
1323 if ( compareBookmarks( _rBookmark, m_aBookmark ) == CompareBookmark::EQUAL )
1325 positionCache( CursorMoveDirection::Current );
1326 m_nDeletedPosition = m_pCache->getRow();
1330 void ORowSetBase::onDeletedRow( const Any& _rBookmark, sal_Int32 _nPos )
1332 if ( rowDeleted() )
1334 // if we're a clone, and on a deleted row, and the main RowSet deleted another
1335 // row (only the main RowSet can, clones can't), which is *before* our
1336 // deleted position, then we have to adjust this position
1337 if ( m_bClone && ( _nPos < m_nDeletedPosition ) )
1338 --m_nDeletedPosition;
1339 return;
1342 ::osl::MutexGuard aGuard( *m_pMutex );
1343 if ( compareBookmarks( _rBookmark, m_aBookmark ) == CompareBookmark::EQUAL )
1345 m_aOldRow->clearRow();
1346 m_aCurrentRow = m_pCache->getEnd();
1347 m_aBookmark = Any();
1351 sal_Int32 ORowSetBase::impl_getRowCount() const
1353 sal_Int32 nRowCount( m_pCache->m_nRowCount );
1354 if ( const_cast< ORowSetBase* >( this )->rowDeleted() && !m_pCache->m_bNew )
1355 ++nRowCount;
1356 return nRowCount;
1360 ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet )
1361 :m_pRowSet( _pRowSet )
1362 ,m_bWasNew( false )
1363 ,m_bWasModified( false )
1366 OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This will crash." );
1368 // remember the "inserted" and "modified" state for later firing
1369 m_bWasNew = m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() );
1370 m_bWasModified = m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() );
1372 // if the row set is on the insert row, then we need to cancel this
1373 if ( m_pRowSet->isModification( ORowSetBase::GrantNotifierAccess() ) )
1374 m_pRowSet->doCancelModification( ORowSetBase::GrantNotifierAccess() );
1377 ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet, ORowSetValueVector::Vector&& i_aRow )
1378 :m_pRowSet( _pRowSet )
1379 ,m_bWasNew( false )
1380 ,m_bWasModified( false )
1382 OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This will crash." );
1383 aRow = std::move(i_aRow); // yes, create a copy to store the old values
1386 ORowSetNotifier::~ORowSetNotifier( )
1390 void ORowSetNotifier::fire()
1392 // we're not interested in firing changes FALSE->TRUE, only TRUE->FALSE.
1393 // (the former would be quite pathological, e.g. after a failed movement)
1395 if ( m_bWasModified
1396 && ( m_bWasModified != m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() ) )
1398 m_pRowSet->fireProperty( PROPERTY_ID_ISMODIFIED, false, true, ORowSetBase::GrantNotifierAccess() );
1400 if ( m_bWasNew
1401 && ( m_bWasNew != m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() ) )
1403 m_pRowSet->fireProperty( PROPERTY_ID_ISNEW, false, true, ORowSetBase::GrantNotifierAccess() );
1406 std::vector<sal_Int32>& ORowSetNotifier::getChangedColumns()
1408 return aChangedColumns;
1411 void ORowSetNotifier::firePropertyChange()
1413 for (auto const& changedColumn : aChangedColumns)
1415 m_pRowSet->firePropertyChange(changedColumn-1, aRow[changedColumn-1], ORowSetBase::GrantNotifierAccess());
1417 if ( !aChangedColumns.empty() )
1418 m_pRowSet->fireProperty(PROPERTY_ID_ISMODIFIED,true,false, ORowSetBase::GrantNotifierAccess());
1421 } // namespace dbaccess
1423 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */