1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
;
59 class OEmptyCollection
: public sdbcx::OCollection
62 virtual void impl_refresh() override
;
63 virtual connectivity::sdbcx::ObjectType
createObject(const OUString
& _rName
) override
;
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();
79 ORowSetBase::ORowSetBase( const Reference
<XComponentContext
>& _rContext
, ::cppu::OBroadcastHelper
& _rBHelper
, ::osl::Mutex
* _pMutex
)
80 :OPropertyStateContainer(_rBHelper
)
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
)
90 ,m_bIgnoreResult(false)
91 ,m_bBeforeFirst(true) // changed from sal_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()
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
);
122 aRet
= OPropertyStateContainer::queryInterface(rType
);
126 void SAL_CALL
ORowSetBase::getFastPropertyValue(Any
& rValue
,sal_Int32 nHandle
) const
132 case PROPERTY_ID_ROWCOUNT
:
133 rValue
<<= impl_getRowCount();
135 case PROPERTY_ID_ISROWCOUNTFINAL
:
136 rValue
<<= m_pCache
->m_bRowCountFinal
;
139 OPropertyStateContainer::getFastPropertyValue(rValue
,nHandle
);
143 OPropertyStateContainer::getFastPropertyValue(rValue
,nHandle
);
147 void SAL_CALL
ORowSetBase::disposing()
149 MutexGuard
aGuard(*m_pMutex
);
153 TDataColumns().swap(m_aDataColumns
);
154 m_pColumns
->disposing();
158 m_pCache
->deregisterOldRow(m_aOldRow
);
159 m_pCache
->deleteIterator(this);
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();
179 sal_Bool SAL_CALL
ORowSetBase::wasNull( )
181 ::osl::MutexGuard
aGuard( *m_pMutex
);
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
)
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!");
235 ORowSetRow rRow
= *m_aCurrentRow
;
236 bool bValidPosition
= rRow
.is() && o3tl::make_unsigned(columnIndex
) < rRow
->size();
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
);
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() )
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
);
369 return getValue(columnIndex
).makeAny();
372 Reference
< XRef
> SAL_CALL
ORowSetBase::getRef( sal_Int32
/*columnIndex*/ )
374 ::dbtools::throwFeatureNotImplementedSQLException( "XRow::getRef", *m_pMySelf
);
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
);
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
);
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!" );
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");
423 SAL_WARN("dbaccess", "Bookmark is not valid");
424 throwFunctionSequenceException(*m_pMySelf
);
429 bool bRet( notifyAllListenersCursorBeforeMove( aGuard
) );
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( );
444 // notification order
447 setCurrentRow( true, true, aOldValues
, aGuard
);
458 SAL_INFO("dbaccess", "ORowSetBase::moveToBookmark(Any) = " << bRet
<< " Clone = " << m_bClone
);
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
) );
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( );
486 // notification order
489 setCurrentRow( true, true, aOldValues
, aGuard
);
498 // RowCount/IsRowCountFinal
501 SAL_INFO("dbaccess", "ORowSetBase::moveRelativeToBookmark(Any," << rows
<< ") = " << bRet
<< " Clone = " << m_bClone
);
505 sal_Int32 SAL_CALL
ORowSetBase::compareBookmarks( const Any
& _first
, const Any
& _second
)
507 ::osl::MutexGuard
aGuard( *m_pMutex
);
509 return m_pCache
->compareBookmarks(_first
,_second
);
512 sal_Bool SAL_CALL
ORowSetBase::hasOrderedBookmarks( )
514 ::osl::MutexGuard
aGuard( *m_pMutex
);
516 return m_pCache
->hasOrderedBookmarks();
519 sal_Int32 SAL_CALL
ORowSetBase::hashBookmark( const Any
& bookmark
)
521 ::osl::MutexGuard
aGuard( *m_pMutex
);
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
;
533 xMeta
= m_pCache
->getMetaData();
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
);
556 if (!m_pEmptyCollection
)
557 m_pEmptyCollection
.reset( new OEmptyCollection(*m_pMySelf
,m_aColumnsMutex
) );
558 return m_pEmptyCollection
.get();
561 return m_pColumns
.get();
565 sal_Bool SAL_CALL
ORowSetBase::next( )
567 SAL_INFO("dbaccess", "ORowSetBase::next() Clone = " << m_bClone
);
568 ::osl::ResettableMutexGuard
aGuard( *m_pMutex
);
571 bool bRet( notifyAllListenersCursorBeforeMove( aGuard
) );
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()
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())
596 assert(m_pCache
->isAfterLast());
598 // in which case we *did* move the cursor
599 if ( bRet
|| bAfterLast
!= m_pCache
->isAfterLast() )
601 // notification order
604 setCurrentRow( true, true, aOldValues
, aGuard
);
605 OSL_ENSURE(!m_bBeforeFirst
,"BeforeFirst is true. I don't know why?");
609 // moved after the last row
611 OSL_ENSURE(m_bAfterLast
,"AfterLast is false. I don't know why?");
618 // - RowCount/IsRowCountFinal
621 SAL_INFO("dbaccess", "ORowSetBase::next() = " << bRet
<< " Clone = " << m_bClone
);
625 sal_Bool SAL_CALL
ORowSetBase::isBeforeFirst( )
627 ::connectivity::checkDisposed(m_rBHelper
.bDisposed
);
628 ::osl::MutexGuard
aGuard( *m_pMutex
);
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
);
641 SAL_INFO("dbaccess", "ORowSetBase::isAfterLast() = " << m_bAfterLast
<< " Clone = " << m_bClone
);
646 bool ORowSetBase::isOnFirst()
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
);
659 if ( m_bBeforeFirst
|| m_bAfterLast
)
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
);
672 bool ORowSetBase::isOnLast()
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
);
684 if ( m_bBeforeFirst
|| m_bAfterLast
)
687 if ( impl_rowDeleted() )
689 if ( !m_pCache
->m_bRowCountFinal
)
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
);
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
727 setCurrentRow( true, true, aOldValues
, aGuard
);
733 // - RowCount/IsRowCountFinal
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
761 ORowSetRow aOldValues
= getOldRow(bWasNew
);
763 m_pCache
->afterLast();
764 doCancelModification( );
766 // notification order
769 setCurrentRow( true, true, aOldValues
, aGuard
);
775 // - RowCount/IsRowCountFinal
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
) );
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( );
808 // notification order
811 setCurrentRow( bMoved
, true, aOldValues
, aGuard
);
814 { // first goes wrong so there is no row
822 // - RowCount/IsRowCountFinal
825 SAL_INFO("dbaccess", "ORowSetBase::move() = " << bRet
<< " Clone = " << m_bClone
);
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
);
851 return impl_getRow();
854 sal_Int32
ORowSetBase::impl_getRow()
857 if ( m_bBeforeFirst
)
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
)
867 positionCache( CursorMoveDirection::Current
);
868 nPos
= m_pCache
->getRow();
870 SAL_INFO("dbaccess", "ORowSetBase::impl_getRow() = " << nPos
<< " Clone = " << m_bClone
);
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
);
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( );
898 // notification order
901 setCurrentRow( true, true, aOldValues
, aGuard
);
904 { // absolute movement goes wrong we stand left or right side of the rows
912 // - RowCount/IsRowCountFinal
915 SAL_INFO("dbaccess", "ORowSetBase::absolute(" << row
<< ") = " << bRet
<< " Clone = " << m_bClone
);
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
);
927 return true; // in this case do nothing
929 checkPositioningAllowed();
932 ( ( !m_bAfterLast
|| rows
<= 0 )
933 && ( !m_bBeforeFirst
|| rows
>= 0 )
934 && notifyAllListenersCursorBeforeMove( aGuard
)
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( );
953 // notification order
956 setCurrentRow( true, true, aOldValues
, aGuard
);
967 // - RowCount/IsRowCountFinal
970 SAL_INFO("dbaccess", "ORowSetBase::relative(" << rows
<< ") = " << bRet
<< " Clone = " << m_bClone
);
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
);
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
1005 setCurrentRow( true, true, aOldValues
, aGuard
);
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
1019 // - RowCount/IsRowCountFinal
1022 SAL_INFO("dbaccess", "ORowSetBase::previous() = " << bRet
<< " Clone = " << m_bClone
);
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!");
1051 // notification order
1054 firePropertyChange(_rOldValues
);
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
)
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()
1086 void SAL_CALL
ORowSetBase::refreshRow( )
1088 ::connectivity::checkDisposed(m_rBHelper
.bDisposed
);
1089 ::osl::MutexGuard
aGuard( *m_pMutex
);
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
);
1109 if ( impl_rowDeleted() )
1112 return m_pCache
->rowUpdated();
1115 sal_Bool SAL_CALL
ORowSetBase::rowInserted( )
1117 ::osl::MutexGuard
aGuard( *m_pMutex
);
1121 if ( impl_rowDeleted() )
1124 return m_pCache
->rowInserted();
1127 sal_Bool SAL_CALL
ORowSetBase::rowDeleted( )
1129 ::osl::MutexGuard
aGuard( *m_pMutex
);
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
);
1146 Reference
< XWarningsSupplier
> xWarnings( m_pCache
->m_xSet
.get(), UNO_QUERY
);
1147 if ( xWarnings
.is() )
1148 return xWarnings
->getWarnings();
1154 void SAL_CALL
ORowSetBase::clearWarnings( )
1156 ::osl::MutexGuard
aGuard( *m_pMutex
);
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())
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!");
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
);
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*/)
1205 void ORowSetBase::notifyAllListenersCursorMoved(::osl::ResettableMutexGuard
& /*_rGuard*/)
1209 bool ORowSetBase::isPropertyChangeNotificationEnabled() const
1214 void ORowSetBase::fireProperty( sal_Int32 _nProperty
, bool _bNew
, bool _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
);
1237 if ( m_bBeforeFirst
)
1239 m_pCache
->beforeFirst();
1242 else if ( m_bAfterLast
)
1244 m_pCache
->afterLast();
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 );
1257 m_pCache
->beforeFirst();
1262 case CursorMoveDirection::Backward
:
1263 if ( m_pCache
->m_bRowCountFinal
&& ( m_nDeletedPosition
== impl_getRowCount() ) )
1265 m_pCache
->afterLast();
1269 bSuccess
= m_pCache
->absolute( m_nDeletedPosition
);
1272 case CursorMoveDirection::Current
:
1273 case CursorMoveDirection::CurrentRefresh
:
1274 bSuccess
= false; // will be asserted below
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
);
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
1312 void ORowSetBase::getPropertyDefaultByHandle( sal_Int32
/*_nHandle*/, Any
& _rDefault
) const
1317 void ORowSetBase::onDeleteRow( const Any
& _rBookmark
)
1320 // not interested in
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
)
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
;
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
)
1362 ORowSetNotifier::ORowSetNotifier( ORowSetBase
* _pRowSet
)
1363 :m_pRowSet( _pRowSet
)
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
)
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)
1398 && ( m_bWasModified
!= m_pRowSet
->isModified( ORowSetBase::GrantNotifierAccess() ) )
1400 m_pRowSet
->fireProperty( PROPERTY_ID_ISMODIFIED
, false, true, ORowSetBase::GrantNotifierAccess() );
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: */