Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/dbaccess/source/core/api/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 43 kB image not shown  

Quelle  RowSetBase.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include "RowSetBase.hxx"
#include "CRowSetDataColumn.hxx"
#include <connectivity/sdbcx/VCollection.hxx>
#include "RowSetCache.hxx"
#include <stringconstants.hxx>
#include <sal/log.hxx>
#include <core_resource.hxx>
#include <strings.hrc>
#include <strings.hxx>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/sdbcx/CompareBookmark.hpp>
#include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
#include <com/sun/star/sdbc/ResultSetType.hpp>
#include <comphelper/sequence.hxx>
#include <comphelper/seqstream.hxx>
#include <connectivity/dbexception.hxx>
#include <o3tl/safeint.hxx>
#include <comphelper/diagnose_ex.hxx>

using namespace dbaccess;
using namespace connectivity;
using namespace connectivity::sdbcx;
using namespace comphelper;
using namespace dbtools;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::sdb;
using namespace ::com::sun::star::sdbcx;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::util;
using namespace ::cppu;
using namespace ::osl;

namespace dbaccess
{

// OEmptyCollection
class OEmptyCollection : public sdbcx::OCollection
{
protected:
    virtual void impl_refresh() override;
    virtual css::uno::Reference< css::beans::XPropertySet > createObject(const OUString& ;_rName) override;
public:
    OEmptyCollection(::cppu::OWeakObject& _rParent,::osl::Mutex& _rMutex) : OCollection(_rParent, true, _rMutex, std::vector< OUString>()){}
};

void OEmptyCollection::impl_refresh()
{
}

css::uno::Reference< css::beans::XPropertySet > OEmptyCollection::createObject(const OUString& /*_rName*/)
{
    return css::uno::Reference< css::beans::XPropertySet >();
}

// ORowSetBase

ORowSetBase::ORowSetBase( const Reference<XComponentContext>& _rContext, ::cppu::OBroadcastHelper& _rBHelper, ::osl::Mutex* _pMutex )
    :OPropertyStateContainer(_rBHelper)
    ,m_pMutex(_pMutex)
    ,m_pMySelf(nullptr)
    ,m_rBHelper(_rBHelper)
    ,m_aContext( _rContext )
    ,m_nLastColumnIndex(-1)
    ,m_nDeletedPosition(-1)
    ,m_nResultSetType( ResultSetType::FORWARD_ONLY )
    ,m_nResultSetConcurrency( ResultSetConcurrency::READ_ONLY )
    ,m_bClone(false)
    ,m_bIgnoreResult(false)
    ,m_bBeforeFirst(true// changed from sal_False
    ,m_bAfterLast(false)
    ,m_bIsInsertRow(false)
{
    sal_Int32 nRBT  = PropertyAttribute::READONLY   | PropertyAttribute::BOUND      | PropertyAttribute::TRANSIENT;

    registerPropertyNoMember( PROPERTY_ROWCOUNT,        PROPERTY_ID_ROWCOUNT,        nRBT, cppu::UnoType<sal_Int32>::get(), css::uno::Any(sal_Int32(0)) );
    registerPropertyNoMember( PROPERTY_ISROWCOUNTFINAL, PROPERTY_ID_ISROWCOUNTFINAL, nRBT, cppu::UnoType<bool>::get(), css::uno::Any(false) );
}

ORowSetBase::~ORowSetBase()
{
    if(m_pColumns)
    {
        TDataColumns().swap(m_aDataColumns);
        m_pColumns->acquire();
        m_pColumns->disposing();
    }
}

// css::lang::XTypeProvider
Sequence< Type > ORowSetBase::getTypes()
{
    return ::comphelper::concatSequences(ORowSetBase_BASE::getTypes(),OPropertyStateContainer::getTypes());
}

// css::uno::XInterface
Any ORowSetBase::queryInterface( const Type & rType )
{
    Any aRet = ORowSetBase_BASE::queryInterface(rType);
    if(!aRet.hasValue())
        aRet = OPropertyStateContainer::queryInterface(rType);
    return aRet;
}

void SAL_CALL ORowSetBase::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const
{
    if(m_pCache)
    {
        switch(nHandle)
        {
        case PROPERTY_ID_ROWCOUNT:
            rValue <<= impl_getRowCount();
            break;
        case PROPERTY_ID_ISROWCOUNTFINAL:
            rValue <<= m_pCache->m_bRowCountFinal;
            break;
        default:
            OPropertyStateContainer::getFastPropertyValue(rValue,nHandle);
        }
    }
    else
        OPropertyStateContainer::getFastPropertyValue(rValue,nHandle);
}

// OComponentHelper
void SAL_CALL ORowSetBase::disposing()
{
    MutexGuard aGuard(*m_pMutex);

    if ( m_pColumns )
    {
        TDataColumns().swap(m_aDataColumns);
        m_pColumns->disposing();
    }
    if ( m_pCache )
    {
        m_pCache->deregisterOldRow(m_aOldRow);
        m_pCache->deleteIterator(this);
    }
    m_pCache = nullptr;
}

// comphelper::OPropertyArrayUsageHelper
::cppu::IPropertyArrayHelper* ORowSetBase::createArrayHelper( ) const
{
    Sequence< Property > aProps;
    describeProperties(aProps);
    return new ::cppu::OPropertyArrayHelper(aProps);
}

// cppu::OPropertySetHelper
::cppu::IPropertyArrayHelper& SAL_CALL ORowSetBase::getInfoHelper()
{
    return *getArrayHelper();
}

// XRow
sal_Bool SAL_CALL ORowSetBase::wasNull(  )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    checkCache();
    return !((m_nLastColumnIndex != -1) && !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is())
           || (**m_aCurrentRow)[m_nLastColumnIndex].isNull();
}

const ORowSetValue& ORowSetBase::getValue(sal_Int32 columnIndex)
{
    checkCache();
    return impl_getValue(columnIndex);
}

const ORowSetValue& ORowSetBase::impl_getValue(sal_Int32 columnIndex)
{
    if ( m_bBeforeFirst || m_bAfterLast )
    {
        SAL_WARN("dbaccess""ORowSetBase::getValue: Illegal call here (we're before first or after last)!");
        ::dbtools::throwSQLException( DBA_RES( RID_STR_CURSOR_BEFORE_OR_AFTER ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );
    }

    if ( impl_rowDeleted() )
    {
        return m_aEmptyValue;
    }

    bool bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
    if ( !bValidCurrentRow )
    {
        // currentrow is null when the clone moves the window
        positionCache( CursorMoveDirection::Current );
        m_aCurrentRow   = m_pCache->m_aMatrixIter;
        m_bIsInsertRow  = false;
        OSL_ENSURE(!m_aCurrentRow.isNull(),"ORowSetBase::getValue: we don't stand on a valid row! Row is null.");

        bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
    }

    if ( bValidCurrentRow )
    {
#if OSL_DEBUG_LEVEL > 0
        ORowSetMatrix::const_iterator aCacheEnd;
        ORowSetMatrix::iterator aCurrentRow;
        aCacheEnd = m_pCache->getEnd();
        aCurrentRow = m_aCurrentRow;
        ORowSetCacheMap::const_iterator aCacheIter = m_aCurrentRow.getIter();
        ORowSetCacheIterator_Helper aHelper = aCacheIter->second;
        ORowSetMatrix::const_iterator k = aHelper.aIterator;
        for (; k != m_pCache->getEnd(); ++k)
        {
            ORowSetValueVector* pTemp = k->get();
            OSL_ENSURE( pTemp != reinterpret_cast<void*>(sal_uIntPtr(0xfeeefeee)),"HALT!" );
        }
        OSL_ENSURE(!m_aCurrentRow.isNull() && m_aCurrentRow < m_pCache->getEnd() && aCacheIter != m_pCache->m_aCacheIterators.end(),"Invalid iterator set for currentrow!");
#endif
        ORowSetRow rRow = *m_aCurrentRow;
        bool bValidPosition = rRow.is() && o3tl::make_unsigned(columnIndex) < rRow->size();
        if (!bValidPosition)
        {
            SAL_WARN("dbaccess""ORowSetBase::getValue: Invalid size of vector!");
            ::dbtools::throwSQLException( DBA_RES( RID_STR_CURSOR_BEFORE_OR_AFTER ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );
        }
        m_nLastColumnIndex = columnIndex;
        return (*rRow)[m_nLastColumnIndex];
    }

    // we should normally never reach this
    return m_aEmptyValue;
}

OUString SAL_CALL ORowSetBase::getString( sal_Int32 columnIndex )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    return getValue(columnIndex).getString();
}

sal_Bool SAL_CALL ORowSetBase::getBoolean( sal_Int32 columnIndex )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    return getValue(columnIndex).getBool();
}

sal_Int8 SAL_CALL ORowSetBase::getByte( sal_Int32 columnIndex )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    return getValue(columnIndex).getInt8();
}

sal_Int16 SAL_CALL ORowSetBase::getShort( sal_Int32 columnIndex )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    return getValue(columnIndex).getInt16();
}

sal_Int32 SAL_CALL ORowSetBase::getInt( sal_Int32 columnIndex )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    return getValue(columnIndex).getInt32();
}

sal_Int64 SAL_CALL ORowSetBase::getLong( sal_Int32 columnIndex )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    return getValue(columnIndex).getLong();
}

float SAL_CALL ORowSetBase::getFloat( sal_Int32 columnIndex )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    return getValue(columnIndex).getFloat();
}

double SAL_CALL ORowSetBase::getDouble( sal_Int32 columnIndex )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    return getValue(columnIndex).getDouble();
}

Sequence< sal_Int8 > SAL_CALL ORowSetBase::getBytes( sal_Int32 columnIndex )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    return getValue(columnIndex).getSequence();
}

css::util::Date SAL_CALL ORowSetBase::getDate( sal_Int32 columnIndex )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    return getValue(columnIndex).getDate();
}

css::util::Time SAL_CALL ORowSetBase::getTime( sal_Int32 columnIndex )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    return getValue(columnIndex).getTime();
}

css::util::DateTime SAL_CALL ORowSetBase::getTimestamp( sal_Int32 columnIndex )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    return getValue(columnIndex).getDateTime();
}

Reference< css::io::XInputStream > SAL_CALL ORowSetBase::getBinaryStream( sal_Int32 columnIndex )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    checkCache();

    if ( m_bBeforeFirst || m_bAfterLast )
    {
        SAL_WARN("dbaccess""ORowSetBase::getBinaryStream: Illegal call here (we're before first or after last)!");
        ::dbtools::throwSQLException( DBA_RES( RID_STR_CURSOR_BEFORE_OR_AFTER ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );
    }

    if ( impl_rowDeleted() )
    {
        return nullptr;
    }

    bool bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
    if ( !bValidCurrentRow )
    {
        positionCache( CursorMoveDirection::Current );
        m_aCurrentRow   = m_pCache->m_aMatrixIter;
        m_bIsInsertRow  = false;
        OSL_ENSURE(!m_aCurrentRow.isNull(),"ORowSetBase::getBinaryStream: we don't stand on a valid row! Row is null.");

        bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
    }

    if ( bValidCurrentRow )
    {
        m_nLastColumnIndex = columnIndex;
        return new ::comphelper::SequenceInputStream((**m_aCurrentRow)[m_nLastColumnIndex].getSequence());
    }

    // we should normally never reach this
    return Reference< css::io::XInputStream >();
}

Reference< css::io::XInputStream > SAL_CALL ORowSetBase::getCharacterStream( sal_Int32 columnIndex )
{
    return getBinaryStream(columnIndex);
}

Any SAL_CALL ORowSetBase::getObject( sal_Int32 columnIndex, const Reference< XNameAccess >&&nbsp;/*typeMap*/ )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    checkCache();

    return getValue(columnIndex).makeAny();
}

Reference< XRef > SAL_CALL ORowSetBase::getRef( sal_Int32 /*columnIndex*/ )
{
    ::dbtools::throwFeatureNotImplementedSQLException( u"XRow::getRef"_ustr, *m_pMySelf );
}

Reference< XBlob > SAL_CALL ORowSetBase::getBlob( sal_Int32 columnIndex )
{
    return Reference< XBlob >(getValue(columnIndex).makeAny(),UNO_QUERY);
}

Reference< XClob > SAL_CALL ORowSetBase::getClob( sal_Int32 columnIndex )
{
    return Reference< XClob >(getValue(columnIndex).makeAny(),UNO_QUERY);
}

Reference< XArray > SAL_CALL ORowSetBase::getArray( sal_Int32 /*columnIndex*/ )
{
    ::dbtools::throwFeatureNotImplementedSQLException( u"XRow::getArray"_ustr, *m_pMySelf );
}

// css::sdbcx::XRowLocate
Any SAL_CALL ORowSetBase::getBookmark(  )
{
    SAL_INFO("dbaccess""ORowSetBase::getBookmark() Clone = " << m_bClone);
    ::connectivity::checkDisposed(m_rBHelper.bDisposed);
    ::osl::MutexGuard aGuard( *m_pMutex );
    checkCache();

    if ( m_bBeforeFirst || m_bAfterLast )
        ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_BOOKMARK_BEFORE_OR_AFTER ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );

    if ( impl_rowDeleted() )
        ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_BOOKMARK_DELETED ), StandardSQLState::INVALID_CURSOR_POSITION, *m_pMySelf );

    OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::getBookmark: bookmark has no value!" );
    return m_aBookmark;
}

sal_Bool SAL_CALL ORowSetBase::moveToBookmark( const Any& bookmark )
{
    SAL_INFO("dbaccess""ORowSetBase::moveToBookmark(Any) Clone = " << m_bClone);
    OSL_ENSURE(bookmark.hasValue(),"ORowSetBase::moveToBookmark bookmark has no value!");
    ::osl::ResettableMutexGuard aGuard( *m_pMutex );

    if(!bookmark.hasValue() || m_nResultSetType == ResultSetType::FORWARD_ONLY)
    {
        if(bookmark.hasValue())
            SAL_WARN("dbaccess""MoveToBookmark is not possible when we are only forward");
        else
            SAL_WARN("dbaccess""Bookmark is not valid");
        throwFunctionSequenceException(*m_pMySelf);
    }

    checkCache();

    bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
    if ( bRet )
    {
        // check if we are inserting a row
        bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();

        ORowSetNotifier aNotifier( this );
            // this will call cancelRowModification on the cache if necessary

        ORowSetRow aOldValues = getOldRow(bWasNew);

        bRet = m_pCache->moveToBookmark(bookmark);
        doCancelModification( );
        if(bRet)
        {
            // notification order
            // - column values
            // - cursorMoved
            setCurrentRow( truetrue, aOldValues, aGuard );
        }
        else
        {
            movementFailed();
        }

        // - IsModified
        // - IsNew
        aNotifier.fire( );
    }
    SAL_INFO("dbaccess""ORowSetBase::moveToBookmark(Any) = " << bRet << " Clone = " << m_bClone);
    return bRet;
}

sal_Bool SAL_CALL ORowSetBase::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows )
{
    SAL_INFO("dbaccess""ORowSetBase::moveRelativeToBookmark(Any," << rows << ") Clone = " << m_bClone);
    ::connectivity::checkDisposed(m_rBHelper.bDisposed);

    ::osl::ResettableMutexGuard aGuard( *m_pMutex );

    checkPositioningAllowed();

    bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
    if ( bRet )
    {
        // check if we are inserting a row
        bool bWasNew = m_pCache->m_bNew || rowDeleted();

        ORowSetNotifier aNotifier( this );
            // this will call cancelRowModification on the cache if necessary

        ORowSetRow aOldValues = getOldRow(bWasNew);

        bRet = m_pCache->moveRelativeToBookmark(bookmark,rows);
        doCancelModification( );
        if(bRet)
        {
            // notification order
            // - column values
            // - cursorMoved
            setCurrentRow( truetrue, aOldValues, aGuard );
        }
        else
            movementFailed();

        // - IsModified
        // - IsNew
        aNotifier.fire( );

        // RowCount/IsRowCountFinal
        fireRowcount();
    }
    SAL_INFO("dbaccess""ORowSetBase::moveRelativeToBookmark(Any," << rows << ") = " << bRet << " Clone = " << m_bClone);
    return bRet;
}

sal_Int32 SAL_CALL ORowSetBase::compareBookmarks( const Any& _first, const Any& _second )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    checkCache();
    return m_pCache->compareBookmarks(_first,_second);
}

sal_Bool SAL_CALL ORowSetBase::hasOrderedBookmarks(  )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    checkCache();
    return m_pCache->hasOrderedBookmarks();
}

sal_Int32 SAL_CALL ORowSetBase::hashBookmark( const Any& bookmark )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    checkCache();
    return m_pCache->hashBookmark(bookmark);
}

// XResultSetMetaDataSupplier
Reference< XResultSetMetaData > SAL_CALL ORowSetBase::getMetaData(  )
{
    ::connectivity::checkDisposed(m_rBHelper.bDisposed);

    Reference< XResultSetMetaData > xMeta;
    if(m_pCache)
        xMeta = m_pCache->getMetaData();

    return xMeta;
}

// XColumnLocate
sal_Int32 SAL_CALL ORowSetBase::findColumn( const OUString& columnName )
{
    ::connectivity::checkDisposed(m_rBHelper.bDisposed);

    ::osl::MutexGuard aGuard( m_aColumnsMutex );
    // it is possible to save some time here when we remember the names - position relation in a map
    return m_pColumns ? m_pColumns->findColumn(columnName) : sal_Int32(0);
}

// css::sdbcx::XColumnsSupplier
Reference< XNameAccess > SAL_CALL ORowSetBase::getColumns(  )
{
    ::connectivity::checkDisposed(m_rBHelper.bDisposed);

    ::osl::MutexGuard aGuard( m_aColumnsMutex );
    if(!m_pColumns)
    {
        if (!m_pEmptyCollection)
            m_pEmptyCollection.reset( new OEmptyCollection(*m_pMySelf,m_aColumnsMutex) );
        return m_pEmptyCollection.get();
    }

    return m_pColumns.get();
}

// XResultSet
sal_Bool SAL_CALL ORowSetBase::next(  )
{
    SAL_INFO("dbaccess""ORowSetBase::next() Clone = " << m_bClone);
    ::osl::ResettableMutexGuard aGuard( *m_pMutex );
    checkCache();

    bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
    if ( bRet )
    {
        // check if we are inserting a row
        bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();

        ORowSetNotifier aNotifier( this );
            // this will call cancelRowModification on the cache if necessary

        ORowSetRow aOldValues = getOldRow(bWasNew);

        positionCache( CursorMoveDirection::Forward );
        bool bAfterLast = m_pCache->isAfterLast();
        bRet = m_pCache->next();
        doCancelModification( );

        // if we were afterLast before next() then we still are,
        // i.e. bAfterLast implies m_pCache->isAfterLast()
        if (bAfterLast)
            assert(m_pCache->isAfterLast());
        // so the only way bAfterLast != m_pCache->isAfterLast()
        // would be that we just arrived there,
        if (bAfterLast != m_pCache->isAfterLast())
        {
            assert(!bAfterLast);
            assert(m_pCache->isAfterLast());
        }
        // in which case we *did* move the cursor
        if ( bRet || bAfterLast != m_pCache->isAfterLast() )
        {
            // notification order
            // - column values
            // - cursorMoved
            setCurrentRow( truetrue, aOldValues, aGuard );
            OSL_ENSURE(!m_bBeforeFirst,"BeforeFirst is true. I don't know why?");
        }
        else
        {
            // moved after the last row
            movementFailed();
            OSL_ENSURE(m_bAfterLast,"AfterLast is false. I don't know why?");
        }

        // - IsModified
        // - IsNew
        aNotifier.fire();

        // - RowCount/IsRowCountFinal
        fireRowcount();
    }
    SAL_INFO("dbaccess""ORowSetBase::next() = " << bRet << " Clone = " << m_bClone);
    return bRet;
}

sal_Bool SAL_CALL ORowSetBase::isBeforeFirst(  )
{
    ::connectivity::checkDisposed(m_rBHelper.bDisposed);
    ::osl::MutexGuard aGuard( *m_pMutex );
    checkCache();

    SAL_INFO("dbaccess""ORowSetBase::isBeforeFirst() = " << m_bBeforeFirst << " Clone = " << m_bClone);

    return m_bBeforeFirst;
}

sal_Bool SAL_CALL ORowSetBase::isAfterLast(  )
{
    ::connectivity::checkDisposed(m_rBHelper.bDisposed);
    ::osl::MutexGuard aGuard( *m_pMutex );
    checkCache();
    SAL_INFO("dbaccess""ORowSetBase::isAfterLast() = " << m_bAfterLast << " Clone = " << m_bClone);

    return m_bAfterLast;
}

bool ORowSetBase::isOnFirst()
{
    return isFirst();
}

sal_Bool SAL_CALL ORowSetBase::isFirst(  )
{
    SAL_INFO("dbaccess""ORowSetBase::isFirst() Clone = " << m_bClone);

    ::connectivity::checkDisposed(m_rBHelper.bDisposed);
    ::osl::MutexGuard aGuard( *m_pMutex );
    checkCache();

    if ( m_bBeforeFirst || m_bAfterLast )
        return false;

    if ( impl_rowDeleted() )
        return ( m_nDeletedPosition == 1 );

    positionCache( CursorMoveDirection::Current );
    bool bIsFirst = m_pCache->isFirst();

    SAL_INFO("dbaccess""ORowSetBase::isFirst() = " << bIsFirst << " Clone = " << m_bClone);
    return bIsFirst;
}

bool ORowSetBase::isOnLast()
{
    return isLast();
}

sal_Bool SAL_CALL ORowSetBase::isLast(  )
{
    SAL_INFO("dbaccess""ORowSetBase::isLast() Clone = " << m_bClone);
    ::connectivity::checkDisposed(m_rBHelper.bDisposed);
    ::osl::MutexGuard aGuard( *m_pMutex );
    checkCache();

    if ( m_bBeforeFirst || m_bAfterLast )
        return false;

    if ( impl_rowDeleted() )
    {
        if ( !m_pCache->m_bRowCountFinal )
            return false;
        else
            return ( m_nDeletedPosition == impl_getRowCount() );
    }

    positionCache( CursorMoveDirection::Current );
    bool bIsLast = m_pCache->isLast();

    SAL_INFO("dbaccess""ORowSetBase::isLast() = " << bIsLast << " Clone = " << m_bClone);
    return bIsLast;
}

void SAL_CALL ORowSetBase::beforeFirst(  )
{
    SAL_INFO("dbaccess""ORowSetBase::beforeFirst() Clone = " << m_bClone);
    ::connectivity::checkDisposed(m_rBHelper.bDisposed);
    ::osl::ResettableMutexGuard aGuard( *m_pMutex );

    checkPositioningAllowed();

    // check if we are inserting a row
    bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();

    if((bWasNew || !m_bBeforeFirst) && notifyAllListenersCursorBeforeMove(aGuard) )
    {
        ORowSetNotifier aNotifier( this );
            // this will call cancelRowModification on the cache if necessary

        if ( !m_bBeforeFirst )
        {
            ORowSetRow aOldValues = getOldRow(bWasNew);
            m_pCache->beforeFirst();
            doCancelModification( );

            // notification order
            // - column values
            // - cursorMoved
            setCurrentRow( truetrue, aOldValues, aGuard );

            // - IsModified
            // - Isnew
            aNotifier.fire();

            // - RowCount/IsRowCountFinal
            fireRowcount();
        }

        // to be done _after_ the notifications!
        m_aOldRow->clearRow();
    }
    SAL_INFO("dbaccess""ORowSetBase::beforeFirst() Clone = " << m_bClone);
}

void SAL_CALL ORowSetBase::afterLast(  )
{
    SAL_INFO("dbaccess""ORowSetBase::afterLast() Clone = " << m_bClone);
    ::connectivity::checkDisposed(m_rBHelper.bDisposed);

    ::osl::ResettableMutexGuard aGuard( *m_pMutex );
    checkPositioningAllowed();

    bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();

    if((bWasNew || !m_bAfterLast) && notifyAllListenersCursorBeforeMove(aGuard) )
    {
        // check if we are inserting a row
        ORowSetNotifier aNotifier( this );
            // this will call cancelRowModification on the cache if necessary

        if(!m_bAfterLast)
        {
            ORowSetRow aOldValues = getOldRow(bWasNew);

            m_pCache->afterLast();
            doCancelModification( );

            // notification order
            // - column values
            // - cursorMoved
            setCurrentRow( truetrue, aOldValues, aGuard );

            // - IsModified
            // - Isnew
            aNotifier.fire();

            // - RowCount/IsRowCountFinal
            fireRowcount();
        }
    }
    SAL_INFO("dbaccess""ORowSetBase::afterLast() Clone = " << m_bClone);
}

bool SAL_CALL ORowSetBase::move(std::function<bool(ORowSetBase *)> const & _aCheckFunctor,
                                std::function<bool(ORowSetCache *)> const & _aMovementFunctor)
{
    SAL_INFO("dbaccess""ORowSetBase::move() Clone = " << m_bClone);
    ::connectivity::checkDisposed(m_rBHelper.bDisposed);
    ::osl::ResettableMutexGuard aGuard( *m_pMutex );
    checkPositioningAllowed();

    bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
    if( bRet )
    {
        // check if we are inserting a row
        bool bWasNew = m_pCache->m_bNew || rowDeleted();

        ORowSetNotifier aNotifier( this );
            // this will call cancelRowModification on the cache if necessary

        ORowSetRow aOldValues = getOldRow(bWasNew);

        bool bMoved = ( bWasNew || !_aCheckFunctor(this) );

        bRet = _aMovementFunctor(m_pCache.get());
        doCancelModification( );

        if ( bRet )
        {
            // notification order
            // - column values
            // - cursorMoved
            setCurrentRow( bMoved, true, aOldValues, aGuard );
        }
        else
        {   // first goes wrong so there is no row
            movementFailed();
        }

        // - IsModified
        // - IsNew
        aNotifier.fire();

        // - RowCount/IsRowCountFinal
        fireRowcount();
    }
    SAL_INFO("dbaccess""ORowSetBase::move() = " << bRet << " Clone = " << m_bClone);
    return bRet;
}

sal_Bool SAL_CALL ORowSetBase::first(  )
{
    SAL_INFO("dbaccess""ORowSetBase::first() Clone = " << m_bClone);
    auto ioF_tmp = std::mem_fn(&ORowSetBase::isOnFirst);
    auto F_tmp = std::mem_fn(&ORowSetCache::first);
    return move(ioF_tmp,F_tmp);
}

sal_Bool SAL_CALL ORowSetBase::last(  )
{
    SAL_INFO("dbaccess""ORowSetBase::last() Clone = " << m_bClone);
    auto ioL_tmp = std::mem_fn(&ORowSetBase::isOnLast);
    auto L_tmp = std::mem_fn(&ORowSetCache::last);
    return move(ioL_tmp,L_tmp);
}

sal_Int32 SAL_CALL ORowSetBase::getRow(  )
{
    SAL_INFO("dbaccess""ORowSetBase::getRow() Clone = " << m_bClone);
    ::osl::MutexGuard aGuard( *m_pMutex );

    checkCache();
    return impl_getRow();
}

sal_Int32 ORowSetBase::impl_getRow()
{
    sal_Int32  nPos = 0;
    if ( m_bBeforeFirst )
        nPos = 0;
    else if ( m_bAfterLast )
        nPos = impl_getRowCount() + 1;
    else if ( impl_rowDeleted() )
        nPos = m_nDeletedPosition;
    else if ( !m_bClone && m_pCache->m_bNew )
        nPos = 0;
    else
    {
        positionCache( CursorMoveDirection::Current );
        nPos = m_pCache->getRow();
    }
    SAL_INFO("dbaccess""ORowSetBase::impl_getRow() = " << nPos << " Clone = " << m_bClone);
    return nPos;
}

sal_Bool SAL_CALL ORowSetBase::absolute( sal_Int32 row )
{
    SAL_INFO("dbaccess""ORowSetBase::absolute(" << row << ") Clone = " << m_bClone);
    ::connectivity::checkDisposed(m_rBHelper.bDisposed);
    ::osl::ResettableMutexGuard aGuard( *m_pMutex );
    checkPositioningAllowed();

    bool bRet = ( row > 0 )
                &&  notifyAllListenersCursorBeforeMove( aGuard );
    if ( bRet )
    {
        // check if we are inserting a row
        bool bWasNew = m_pCache->m_bNew || rowDeleted();

        ORowSetNotifier aNotifier( this );
            // this will call cancelRowModification on the cache if necessary

        ORowSetRow aOldValues = getOldRow(bWasNew);

        bRet = m_pCache->absolute(row);
        doCancelModification( );

        if(bRet)
        {
            // notification order
            // - column values
            // - cursorMoved
            setCurrentRow( truetrue, aOldValues, aGuard );
        }
        else
        { // absolute movement goes wrong we stand left or right side of the rows
            movementFailed();
        }

        // - IsModified
        // - IsNew
        aNotifier.fire();

        // - RowCount/IsRowCountFinal
        fireRowcount();
    }
    SAL_INFO("dbaccess""ORowSetBase::absolute(" << row << ") = " << bRet << " Clone = " << m_bClone);
    return bRet;
}

sal_Bool SAL_CALL ORowSetBase::relative( sal_Int32 rows )
{
    SAL_INFO("dbaccess""ORowSetBase::relative(" << rows << ") Clone = " << m_bClone);
    ::connectivity::checkDisposed(m_rBHelper.bDisposed);

    ::osl::ResettableMutexGuard aGuard( *m_pMutex );

    if(!rows)
        return true// in this case do nothing

    checkPositioningAllowed();

    bool bRet =
            (  ( !m_bAfterLast || rows <= 0 )
            && ( !m_bBeforeFirst || rows >= 0 )
            && notifyAllListenersCursorBeforeMove( aGuard )
            );

    if ( bRet )
    {
        // check if we are inserting a row
        bool bWasNew = m_pCache->m_bNew || rowDeleted();

        ORowSetNotifier aNotifier( this );
            // this will call cancelRowModification on the cache if necessary

        ORowSetRow aOldValues = getOldRow(bWasNew);

        positionCache( rows > 0 ? CursorMoveDirection::Forward : CursorMoveDirection::Backward );
        bRet = m_pCache->relative(rows);
        doCancelModification( );

        if(bRet)
        {
            // notification order
            // - column values
            // - cursorMoved
            setCurrentRow( truetrue, aOldValues, aGuard );
        }
        else
        {
            movementFailed();
        }

        // - IsModified
        // - IsNew
        aNotifier.fire();

        // - RowCount/IsRowCountFinal
        fireRowcount();
    }
    SAL_INFO("dbaccess""ORowSetBase::relative(" << rows << ") = " << bRet << " Clone = " << m_bClone);
    return bRet;
}

sal_Bool SAL_CALL ORowSetBase::previous(  )
{
    SAL_INFO("dbaccess""ORowSetBase::previous() Clone = " << m_bClone);
    ::connectivity::checkDisposed(m_rBHelper.bDisposed);
    ::osl::ResettableMutexGuard aGuard( *m_pMutex );

    checkPositioningAllowed();

    bool bRet = !m_bBeforeFirst
                &&  notifyAllListenersCursorBeforeMove(aGuard);

    if ( bRet )
    {
        // check if we are inserting a row
        bool bWasNew = m_pCache->m_bNew || rowDeleted();

        ORowSetNotifier aNotifier( this );
            // this will call cancelRowModification on the cache if necessary

        ORowSetRow aOldValues = getOldRow(bWasNew);

        positionCache( CursorMoveDirection::Backward );
        bRet = m_pCache->previous();
        doCancelModification( );

        // if m_bBeforeFirst is false and bRet is false then we stood on the first row
        if(!m_bBeforeFirst || bRet)
        {
            // notification order
            // - column values
            // - cursorMoved
            setCurrentRow( truetrue, aOldValues, aGuard );
        }
        else
        {
            SAL_WARN("dbaccess""ORowSetBase::previous: inconsistency!" );
                // we should never reach this place, as we should not get into this whole branch if m_bBeforeFirst
                // was |true| from the beginning
            movementFailed();
        }

        // - IsModified
        // - IsNew
        aNotifier.fire();

        // - RowCount/IsRowCountFinal
        fireRowcount();
    }
    SAL_INFO("dbaccess""ORowSetBase::previous() = " << bRet << " Clone = " << m_bClone);
    return bRet;
}

void ORowSetBase::setCurrentRow( bool _bMoved, bool _bDoNotify, const ORowSetRow& _rOldValues, ::osl::ResettableMutexGuard& _rGuard )
{
    SAL_INFO("dbaccess""ORowSetBase::setCurrentRow() Clone = " << m_bClone);
    m_bBeforeFirst  = m_pCache->isBeforeFirst();
    m_bAfterLast    = m_pCache->isAfterLast();

    if(!(m_bBeforeFirst || m_bAfterLast))
    {
        m_aBookmark     = m_pCache->getBookmark();
        OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!");
        m_aCurrentRow   = m_pCache->m_aMatrixIter;
        m_bIsInsertRow  = false;
        OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is null!");
        OSL_ENSURE(!m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd(),"Position of matrix iterator isn't valid!");
        OSL_ENSURE(m_aCurrentRow->is(),"Currentrow isn't valid");
        OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!");

        m_aCurrentRow   = m_pCache->m_aMatrixIter;
        m_bIsInsertRow  = false;
        OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is nul after positionCache!");
#if OSL_DEBUG_LEVEL > 0
        ORowSetRow rRow = *m_aCurrentRow;
        OSL_ENSURE(rRow.is() ,"Invalid size of vector!");
#endif

        // notification order
        // - column values
        if ( _bDoNotify )
            firePropertyChange(_rOldValues);

    }
    else
    {
        m_aOldRow->clearRow();
        m_aCurrentRow   = m_pCache->getEnd();
        m_aBookmark     = Any();
    }

    // TODO: can this be done before the notifications?
    if(!(m_bBeforeFirst || m_bAfterLast) && !m_aCurrentRow.isNull() && m_aCurrentRow->is() && m_aCurrentRow != m_pCache->getEnd())
        m_aOldRow->setRow(new ORowSetValueVector( *(*m_aCurrentRow) ));

    if ( _bMoved && _bDoNotify )
        // - cursorMoved
        notifyAllListenersCursorMoved( _rGuard );

    SAL_INFO("dbaccess""ORowSetBase::setCurrentRow() Clone = " << m_bClone);
}

void ORowSetBase::checkPositioningAllowed()
{
    if(!m_pCache || m_nResultSetType == ResultSetType::FORWARD_ONLY)
        throwFunctionSequenceException(*m_pMySelf);
}

Reference< XInterface >  ORowSetBase::getStatement()
{
    return nullptr;
}

void SAL_CALL ORowSetBase::refreshRow(  )
{
    ::connectivity::checkDisposed(m_rBHelper.bDisposed);
    ::osl::MutexGuard aGuard( *m_pMutex );
    checkCache();
    if ( impl_rowDeleted() )
        throwSQLException( u"The current row is deleted"_ustr, StandardSQLState::INVALID_CURSOR_STATE, Reference< XRowSet >( this ) );

    if(!(m_bBeforeFirst || m_bAfterLast))
    {
        bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
        ORowSetRow aOldValues = getOldRow(bWasNew);
        positionCache( CursorMoveDirection::Current );
        m_pCache->refreshRow();
        firePropertyChange(aOldValues);
    }
}

sal_Bool SAL_CALL ORowSetBase::rowUpdated(  )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    checkCache();

    if ( impl_rowDeleted() )
        return false;

    return m_pCache->rowUpdated();
}

sal_Bool SAL_CALL ORowSetBase::rowInserted(  )
{
    ::osl::MutexGuard aGuard( *m_pMutex );

    checkCache();

    if ( impl_rowDeleted() )
        return false;

    return m_pCache->rowInserted();
}

sal_Bool SAL_CALL ORowSetBase::rowDeleted(  )
{
    ::osl::MutexGuard aGuard( *m_pMutex );
    checkCache();
    return impl_rowDeleted();
}

bool ORowSetBase::impl_rowDeleted(  )
{
    return !m_aBookmark.hasValue() && !m_bBeforeFirst && !m_bAfterLast;
}

// XWarningsSupplier
Any SAL_CALL ORowSetBase::getWarnings(  )
{
    ::osl::MutexGuard aGuard( *m_pMutex );

    if ( m_pCache )
    {
        Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY );
        if ( xWarnings.is() )
            return xWarnings->getWarnings();
    }

    return Any();
}

void SAL_CALL ORowSetBase::clearWarnings(  )
{
    ::osl::MutexGuard aGuard( *m_pMutex );

    if ( m_pCache )
    {
        Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY );
        if ( xWarnings.is() )
            xWarnings->clearWarnings();
    }
}

void ORowSetBase::firePropertyChange(const ORowSetRow& _rOldRow)
{
    if (!isPropertyChangeNotificationEnabled())
        return;

    SAL_INFO("dbaccess""ORowSetBase::firePropertyChange" );
    SAL_INFO("dbaccess""ORowSetBase::firePropertyChange() Clone = " << m_bClone);
    OSL_ENSURE(m_pColumns,"Columns can not be NULL here!");
    sal_Int32 i=0;
    for (auto const& dataColumn : m_aDataColumns)
    {
        try
        {
            dataColumn->fireValueChange(_rOldRow.is() ? (*_rOldRow)[i+1] : ::connectivity::ORowSetValue());
        }
        catch (const Exception&)
        {
            TOOLS_WARN_EXCEPTION("dbaccess""firePropertyChange: Exception on column " << i);
        }
        ++i;
    }
    SAL_INFO("dbaccess""ORowSetBase::firePropertyChange() Clone = " << m_bClone);
}

void ORowSetBase::firePropertyChange(sal_Int32 _nPos,const ::connectivity::ORowSetValue& _rOldValue)
{
    OSL_ENSURE(_nPos < static_cast<sal_Int32>(m_aDataColumns.size()),"nPos is invalid!");
    m_aDataColumns[_nPos]->fireValueChange(_rOldValue);
}

void ORowSetBase::fireRowcount()
{
}

bool ORowSetBase::notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard&&nbsp;/*_rGuard*/)
{
    return true;
}

void ORowSetBase::notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& /*_rGuard*/)
{
}

bool ORowSetBase::isPropertyChangeNotificationEnabled() const
{
    return true;
}

void ORowSetBase::fireProperty( sal_Int32 _nProperty, bool _bNew, bool _bOld )
{
    Any aNew( _bNew );
    Any aOld( _bOld );
    fire( &_nProperty, &aNew, &aOld, 1, false );
}

void ORowSetBase::positionCache( CursorMoveDirection _ePrepareForDirection )
{
    SAL_INFO("dbaccess""ORowSetBase::positionCache() Clone = " << m_bClone);

    bool bSuccess = false;
    if ( m_aBookmark.hasValue() )
    {
        if (_ePrepareForDirection == CursorMoveDirection::CurrentRefresh ||
            (m_pCache->isAfterLast() != bool(isAfterLast())) || ( m_pCache->isBeforeFirst() != bool(isBeforeFirst()) ) ||
             m_pCache->compareBookmarks( m_aBookmark, m_pCache->getBookmark() ) != CompareBookmark::EQUAL )
            bSuccess = m_pCache->moveToBookmark( m_aBookmark );
        else
            bSuccess = true;
    }
    else
    {
        if ( m_bBeforeFirst )
        {
            m_pCache->beforeFirst();
            bSuccess = true;
        }
        else if ( m_bAfterLast )
        {
            m_pCache->afterLast();
            bSuccess = true;
        }
        else
        {
            OSL_ENSURE( m_nDeletedPosition >= 1, "ORowSetBase::positionCache: no bookmark, and no valid 'deleted position'!" );
            switch ( _ePrepareForDirection )
            {
            case CursorMoveDirection::Forward:
                if ( m_nDeletedPosition > 1 )
                    bSuccess = m_pCache->absolute( m_nDeletedPosition - 1 );
                else
                {
                    m_pCache->beforeFirst();
                    bSuccess = true;
                }
                break;

            case CursorMoveDirection::Backward:
                if ( m_pCache->m_bRowCountFinal && ( m_nDeletedPosition == impl_getRowCount() ) )
                {
                    m_pCache->afterLast();
                    bSuccess = true;
                }
                else
                    bSuccess = m_pCache->absolute( m_nDeletedPosition );
                break;

            case CursorMoveDirection::Current:
            case CursorMoveDirection::CurrentRefresh:
                bSuccess = false;   // will be asserted below
                break;
            }
        }
    }
    OSL_ENSURE( bSuccess, "ORowSetBase::positionCache: failed!" );

    SAL_INFO("dbaccess""ORowSetBase::positionCache() Clone = " << m_bClone);
}

void ORowSetBase::checkCache()
{
    ::connectivity::checkDisposed(m_rBHelper.bDisposed);
    if(!m_pCache)
        throwFunctionSequenceException(*m_pMySelf);
}

void ORowSetBase::movementFailed()
{
    SAL_INFO("dbaccess""ORowSetBase::movementFailed() Clone = " << m_bClone);
    m_aOldRow->clearRow();
    m_aCurrentRow   = m_pCache->getEnd();
    m_bBeforeFirst  = m_pCache->isBeforeFirst();
    m_bAfterLast    = m_pCache->isAfterLast();
    m_aBookmark     = Any();
    OSL_ENSURE(m_bBeforeFirst || m_bAfterLast,"BeforeFirst or AfterLast is wrong!");
    SAL_INFO("dbaccess""ORowSetBase::movementFailed() Clone = " << m_bClone);
}

ORowSetRow ORowSetBase::getOldRow(bool _bWasNew)
{
    OSL_ENSURE(m_aOldRow.is(),"RowSetRowHElper isn't valid!");
    ORowSetRow aOldValues;
    if ( !_bWasNew && m_aOldRow->getRow().is() )
        aOldValues = new ORowSetValueVector( *(m_aOldRow->getRow()));    // remember the old values
    return aOldValues;
}

void ORowSetBase::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const
{
    _rDefault.clear();
}

void ORowSetBase::onDeleteRow( const Any& _rBookmark )
{
    if ( rowDeleted() )
        // not interested in
        return;

    ::osl::MutexGuard aGuard( *m_pMutex );
    //OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::onDeleteRow: Bookmark isn't valid!" );
    if ( compareBookmarks( _rBookmark, m_aBookmark ) == CompareBookmark::EQUAL )
    {
        positionCache( CursorMoveDirection::Current );
        m_nDeletedPosition = m_pCache->getRow();
    }
}

void ORowSetBase::onDeletedRow( const Any& _rBookmark, sal_Int32 _nPos )
{
    if ( rowDeleted() )
    {
        // if we're a clone, and on a deleted row, and the main RowSet deleted another
        // row (only the main RowSet can, clones can't), which is *before* our
        // deleted position, then we have to adjust this position
        if ( m_bClone && ( _nPos < m_nDeletedPosition ) )
            --m_nDeletedPosition;
        return;
    }

    ::osl::MutexGuard aGuard( *m_pMutex );
    if ( compareBookmarks( _rBookmark, m_aBookmark ) == CompareBookmark::EQUAL )
    {
        m_aOldRow->clearRow();
        m_aCurrentRow   = m_pCache->getEnd();
        m_aBookmark     = Any();
    }
}

sal_Int32 ORowSetBase::impl_getRowCount() const
{
    sal_Int32 nRowCount( m_pCache->m_nRowCount );
    if ( const_cast< ORowSetBase* >( this )->rowDeleted() && !m_pCache->m_bNew )
        ++nRowCount;
    return nRowCount;
}


ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet )
    :m_pRowSet( _pRowSet )
    ,m_bWasNew( false )
    ,m_bWasModified( false )
{

    OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This will crash." );

    // remember the "inserted" and "modified" state for later firing
    m_bWasNew       = m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() );
    m_bWasModified  = m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() );

    // if the row set is on the insert row, then we need to cancel this
    if ( m_pRowSet->isModification( ORowSetBase::GrantNotifierAccess() ) )
        m_pRowSet->doCancelModification( ORowSetBase::GrantNotifierAccess() );
}

ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet, ORowSetValueVector::Vector&& i_aRow )
    :m_pRowSet( _pRowSet )
    ,m_bWasNew( false )
    ,m_bWasModified( false )
{
    OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This will crash." );
    aRow = std::move(i_aRow); // yes, create a copy to store the old values
}

ORowSetNotifier::~ORowSetNotifier( )
{
}

void ORowSetNotifier::fire()
{
    // we're not interested in firing changes FALSE->TRUE, only TRUE->FALSE.
    // (the former would be quite pathological, e.g. after a failed movement)

    if  (   m_bWasModified
        &&  ( m_bWasModified != m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() ) )
        )
        m_pRowSet->fireProperty( PROPERTY_ID_ISMODIFIED, falsetrue, ORowSetBase::GrantNotifierAccess() );

    if  (   m_bWasNew
        &&  ( m_bWasNew != m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() ) )
        )
        m_pRowSet->fireProperty( PROPERTY_ID_ISNEW, falsetrue, ORowSetBase::GrantNotifierAccess() );
}

std::vector<sal_Int32>& ORowSetNotifier::getChangedColumns()
{
    return aChangedColumns;
}

void ORowSetNotifier::firePropertyChange()
{
    for (auto const& changedColumn : aChangedColumns)
    {
        m_pRowSet->firePropertyChange(changedColumn-1, aRow[changedColumn-1], ORowSetBase::GrantNotifierAccess());
    }
    if ( !aChangedColumns.empty() )
        m_pRowSet->fireProperty(PROPERTY_ID_ISMODIFIED,true,false, ORowSetBase::GrantNotifierAccess());
}

}   // namespace dbaccess

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

98%


¤ Dauer der Verarbeitung: 0.25 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.