diff options
Diffstat (limited to '')
-rw-r--r-- | ucbhelper/source/provider/resultset.cxx | 1495 |
1 files changed, 1495 insertions, 0 deletions
diff --git a/ucbhelper/source/provider/resultset.cxx b/ucbhelper/source/provider/resultset.cxx new file mode 100644 index 000000000..eff10d5d2 --- /dev/null +++ b/ucbhelper/source/provider/resultset.cxx @@ -0,0 +1,1495 @@ +/* -*- 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 . + */ + + +/************************************************************************** + TODO + ************************************************************************** + + *************************************************************************/ +#include <memory> +#include <mutex> +#include <comphelper/interfacecontainer4.hxx> +#include <comphelper/multiinterfacecontainer4.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/sdbc/SQLException.hpp> +#include <ucbhelper/resultset.hxx> +#include <ucbhelper/resultsetmetadata.hxx> +#include <ucbhelper/macros.hxx> +#include <osl/diagnose.h> + +using namespace com::sun::star; + + +namespace ucbhelper_impl +{ + +namespace { + +struct PropertyInfo +{ + const char* pName; + sal_Int32 nHandle; + sal_Int16 nAttributes; + const uno::Type& (*pGetCppuType)(); +}; + +} + +static const uno::Type& sal_Int32_getCppuType() +{ + return cppu::UnoType<sal_Int32>::get(); +} + +static const uno::Type& sal_Bool_getCppuType() +{ + return cppu::UnoType<bool>::get(); +} + +const PropertyInfo aPropertyTable[] = +{ + { "IsRowCountFinal", + 1000, + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY, + &sal_Bool_getCppuType + }, + { "RowCount", + 1001, + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY, + &sal_Int32_getCppuType + }, + { nullptr, + 0, + 0, + nullptr + } +}; + +#define RESULTSET_PROPERTY_COUNT 2 + + + +namespace { + +class PropertySetInfo : + public cppu::OWeakObject, + public lang::XTypeProvider, + public beans::XPropertySetInfo +{ + uno::Sequence< beans::Property > m_aProps; + +private: + bool queryProperty( + std::u16string_view aName, beans::Property& rProp ) const; + +public: + PropertySetInfo( + const PropertyInfo* pProps, + sal_Int32 nProps ); + + // XInterface + virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override; + virtual void SAL_CALL acquire() + noexcept override; + virtual void SAL_CALL release() + noexcept override; + + // XTypeProvider + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override; + virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override; + + // XPropertySetInfo + virtual uno::Sequence< beans::Property > SAL_CALL getProperties() override; + virtual beans::Property SAL_CALL getPropertyByName( + const OUString& aName ) override; + virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) override; +}; + +} + +typedef comphelper::OMultiTypeInterfaceContainerHelperVar4<OUString, css::beans::XPropertyChangeListener> + PropertyChangeListeners; + +} // namespace ucbhelper_impl + +using namespace ucbhelper_impl; + +namespace ucbhelper +{ + + +// struct ResultSet_Impl. + + +struct ResultSet_Impl +{ + uno::Reference< uno::XComponentContext > m_xContext; + uno::Reference< css::ucb::XCommandEnvironment > m_xEnv; + uno::Reference< beans::XPropertySetInfo > m_xPropSetInfo; + uno::Reference< sdbc::XResultSetMetaData > m_xMetaData; + uno::Sequence< beans::Property > m_aProperties; + rtl::Reference< ResultSetDataSupplier > m_xDataSupplier; + std::mutex m_aMutex; + comphelper::OInterfaceContainerHelper4<lang::XEventListener> m_aDisposeEventListeners; + std::unique_ptr<PropertyChangeListeners> m_pPropertyChangeListeners; + sal_Int32 m_nPos; + bool m_bWasNull; + bool m_bAfterLast; + + inline ResultSet_Impl( + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Sequence< beans::Property >& rProperties, + const rtl::Reference< ResultSetDataSupplier >& rDataSupplier, + const uno::Reference< css::ucb::XCommandEnvironment >& rxEnv ); +}; + +inline ResultSet_Impl::ResultSet_Impl( + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Sequence< beans::Property >& rProperties, + const rtl::Reference< ResultSetDataSupplier >& rDataSupplier, + const uno::Reference< css::ucb::XCommandEnvironment >& rxEnv ) +: m_xContext( rxContext ), + m_xEnv( rxEnv ), + m_aProperties( rProperties ), + m_xDataSupplier( rDataSupplier ), + m_nPos( 0 ), // Position is one-based. Zero means: before first element. + m_bWasNull( false ), + m_bAfterLast( false ) +{ +} + + +// ResultSet Implementation. + + +ResultSet::ResultSet( + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Sequence< beans::Property >& rProperties, + const rtl::Reference< ResultSetDataSupplier >& rDataSupplier ) +: m_pImpl( new ResultSet_Impl( + rxContext, + rProperties, + rDataSupplier, + uno::Reference< css::ucb::XCommandEnvironment >() ) ) +{ + rDataSupplier->m_pResultSet = this; +} + + +ResultSet::ResultSet( + const uno::Reference< uno::XComponentContext >& rxContext, + const uno::Sequence< beans::Property >& rProperties, + const rtl::Reference< ResultSetDataSupplier >& rDataSupplier, + const uno::Reference< css::ucb::XCommandEnvironment >& rxEnv ) +: m_pImpl( new ResultSet_Impl( rxContext, rProperties, rDataSupplier, rxEnv ) ) +{ + rDataSupplier->m_pResultSet = this; +} + + +// virtual +ResultSet::~ResultSet() +{ +} + + +// XServiceInfo methods. + +OUString SAL_CALL ResultSet::getImplementationName() +{ + return "ResultSet"; +} + +sal_Bool SAL_CALL ResultSet::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService( this, ServiceName ); +} + +css::uno::Sequence< OUString > SAL_CALL ResultSet::getSupportedServiceNames() +{ + return { RESULTSET_SERVICE_NAME }; +} + + +// XComponent methods. + + +// virtual +void SAL_CALL ResultSet::dispose() +{ + std::unique_lock aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_aDisposeEventListeners.getLength(aGuard) ) + { + lang::EventObject aEvt; + aEvt.Source = static_cast< lang::XComponent * >( this ); + m_pImpl->m_aDisposeEventListeners.disposeAndClear( aGuard, aEvt ); + } + + if ( m_pImpl->m_pPropertyChangeListeners ) + { + lang::EventObject aEvt; + aEvt.Source = static_cast< beans::XPropertySet * >( this ); + m_pImpl->m_pPropertyChangeListeners->disposeAndClear( aGuard, aEvt ); + } + + m_pImpl->m_xDataSupplier->close(); +} + + +// virtual +void SAL_CALL ResultSet::addEventListener( + const uno::Reference< lang::XEventListener >& Listener ) +{ + std::unique_lock aGuard( m_pImpl->m_aMutex ); + + m_pImpl->m_aDisposeEventListeners.addInterface( aGuard, Listener ); +} + + +// virtual +void SAL_CALL ResultSet::removeEventListener( + const uno::Reference< lang::XEventListener >& Listener ) +{ + std::unique_lock aGuard( m_pImpl->m_aMutex ); + + m_pImpl->m_aDisposeEventListeners.removeInterface( aGuard, Listener ); +} + + +// XResultSetMetaDataSupplier methods. + + +// virtual +uno::Reference< sdbc::XResultSetMetaData > SAL_CALL ResultSet::getMetaData() +{ + std::unique_lock aGuard( m_pImpl->m_aMutex ); + + if ( !m_pImpl->m_xMetaData.is() ) + m_pImpl->m_xMetaData = new ResultSetMetaData( m_pImpl->m_xContext, + m_pImpl->m_aProperties ); + + return m_pImpl->m_xMetaData; +} + + +// XResultSet methods. + + +// virtual +sal_Bool SAL_CALL ResultSet::next() +{ + // Note: Cursor is initially positioned before the first row. + // First call to 'next()' moves it to first row. + + std::unique_lock aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_bAfterLast ) + { + m_pImpl->m_xDataSupplier->validate(); + return false; + } + + // getResult works zero-based! + if ( !m_pImpl->m_xDataSupplier->getResult( m_pImpl->m_nPos ) ) + { + m_pImpl->m_bAfterLast = true; + m_pImpl->m_xDataSupplier->validate(); + return false; + } + + m_pImpl->m_nPos++; + m_pImpl->m_xDataSupplier->validate(); + return true; +} + + +// virtual +sal_Bool SAL_CALL ResultSet::isBeforeFirst() +{ + if ( m_pImpl->m_bAfterLast ) + { + m_pImpl->m_xDataSupplier->validate(); + return false; + } + + // getResult works zero-based! + if ( !m_pImpl->m_xDataSupplier->getResult( 0 ) ) + { + m_pImpl->m_xDataSupplier->validate(); + return false; + } + + m_pImpl->m_xDataSupplier->validate(); + return ( m_pImpl->m_nPos == 0 ); +} + + +// virtual +sal_Bool SAL_CALL ResultSet::isAfterLast() +{ + m_pImpl->m_xDataSupplier->validate(); + return m_pImpl->m_bAfterLast; +} + + +// virtual +sal_Bool SAL_CALL ResultSet::isFirst() +{ + if ( m_pImpl->m_bAfterLast ) + { + m_pImpl->m_xDataSupplier->validate(); + return false; + } + + m_pImpl->m_xDataSupplier->validate(); + return ( m_pImpl->m_nPos == 1 ); +} + + +// virtual +sal_Bool SAL_CALL ResultSet::isLast() +{ + if ( m_pImpl->m_bAfterLast ) + { + m_pImpl->m_xDataSupplier->validate(); + return false; + } + + sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount(); + if ( !nCount ) + { + m_pImpl->m_xDataSupplier->validate(); + return false; + } + + m_pImpl->m_xDataSupplier->validate(); + return ( m_pImpl->m_nPos == nCount ); +} + + +// virtual +void SAL_CALL ResultSet::beforeFirst() +{ + std::unique_lock aGuard( m_pImpl->m_aMutex ); + m_pImpl->m_bAfterLast = false; + m_pImpl->m_nPos = 0; + m_pImpl->m_xDataSupplier->validate(); +} + + +// virtual +void SAL_CALL ResultSet::afterLast() +{ + std::unique_lock aGuard( m_pImpl->m_aMutex ); + m_pImpl->m_bAfterLast = true; + m_pImpl->m_xDataSupplier->validate(); +} + + +// virtual +sal_Bool SAL_CALL ResultSet::first() +{ + // getResult works zero-based! + if ( m_pImpl->m_xDataSupplier->getResult( 0 ) ) + { + std::unique_lock aGuard( m_pImpl->m_aMutex ); + m_pImpl->m_bAfterLast = false; + m_pImpl->m_nPos = 1; + m_pImpl->m_xDataSupplier->validate(); + return true; + } + + m_pImpl->m_xDataSupplier->validate(); + return false; +} + + +// virtual +sal_Bool SAL_CALL ResultSet::last() +{ + sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount(); + if ( nCount ) + { + std::unique_lock aGuard( m_pImpl->m_aMutex ); + m_pImpl->m_bAfterLast = false; + m_pImpl->m_nPos = nCount; + m_pImpl->m_xDataSupplier->validate(); + return true; + } + + m_pImpl->m_xDataSupplier->validate(); + return false; +} + + +// virtual +sal_Int32 SAL_CALL ResultSet::getRow() +{ + if ( m_pImpl->m_bAfterLast ) + { + m_pImpl->m_xDataSupplier->validate(); + return 0; + } + + m_pImpl->m_xDataSupplier->validate(); + return m_pImpl->m_nPos; +} + + +// virtual +sal_Bool SAL_CALL ResultSet::absolute( sal_Int32 row ) +{ +/* + If the row number is positive, the cursor moves to the given row number + with respect to the beginning of the result set. The first row is row 1, + the second is row 2, and so on. + + If the given row number is negative, the cursor moves to an absolute row + position with respect to the end of the result set. For example, calling + absolute( -1 ) positions the cursor on the last row, absolute( -2 ) + indicates the next-to-last row, and so on. + + An attempt to position the cursor beyond the first/last row in the result + set leaves the cursor before/after the first/last row, respectively. + + Calling absolute( 1 ) is the same as calling first(). + + Calling absolute( -1 ) is the same as calling last(). +*/ + if ( row < 0 ) + { + sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount(); + + if ( ( row * -1 ) > nCount ) + { + std::unique_lock aGuard( m_pImpl->m_aMutex ); + m_pImpl->m_bAfterLast = false; + m_pImpl->m_nPos = 0; + m_pImpl->m_xDataSupplier->validate(); + return false; + } + else // |row| <= nCount + { + std::unique_lock aGuard( m_pImpl->m_aMutex ); + m_pImpl->m_bAfterLast = false; + m_pImpl->m_nPos = ( nCount + row + 1 ); + m_pImpl->m_xDataSupplier->validate(); + return true; + } + } + else if ( row == 0 ) + { + // @throws SQLException + // ... if row is 0 ... + throw sdbc::SQLException(); + } + else // row > 0 + { + sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount(); + + if ( row <= nCount ) + { + std::unique_lock aGuard( m_pImpl->m_aMutex ); + m_pImpl->m_bAfterLast = false; + m_pImpl->m_nPos = row; + m_pImpl->m_xDataSupplier->validate(); + return true; + } + else // row > nCount + { + std::unique_lock aGuard( m_pImpl->m_aMutex ); + m_pImpl->m_bAfterLast = true; + m_pImpl->m_xDataSupplier->validate(); + return false; + } + } + + // unreachable... +} + + +// virtual +sal_Bool SAL_CALL ResultSet::relative( sal_Int32 rows ) +{ +/* + Attempting to move beyond the first/last row in the result set + positions the cursor before/after the first/last row. + + Calling relative( 0 ) is valid, but does not change the cursor position. + + Calling relative( 1 ) is different from calling next() because it makes + sense to call next() when there is no current row, for example, when + the cursor is positioned before the first row or after the last row of + the result set. +*/ + if ( m_pImpl->m_bAfterLast || ( m_pImpl->m_nPos == 0 ) ) + { + // "No current row". + throw sdbc::SQLException(); + } + + if ( rows < 0 ) + { + if ( ( m_pImpl->m_nPos + rows ) > 0 ) + { + std::unique_lock aGuard( m_pImpl->m_aMutex ); + m_pImpl->m_bAfterLast = false; + m_pImpl->m_nPos = ( m_pImpl->m_nPos + rows ); + m_pImpl->m_xDataSupplier->validate(); + return true; + } + else + { + std::unique_lock aGuard( m_pImpl->m_aMutex ); + m_pImpl->m_bAfterLast = false; + m_pImpl->m_nPos = 0; + m_pImpl->m_xDataSupplier->validate(); + return false; + } + } + else if ( rows == 0 ) + { + // nop. + m_pImpl->m_xDataSupplier->validate(); + return true; + } + else // rows > 0 + { + sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount(); + if ( ( m_pImpl->m_nPos + rows ) <= nCount ) + { + std::unique_lock aGuard( m_pImpl->m_aMutex ); + m_pImpl->m_bAfterLast = false; + m_pImpl->m_nPos = ( m_pImpl->m_nPos + rows ); + m_pImpl->m_xDataSupplier->validate(); + return true; + } + else + { + std::unique_lock aGuard( m_pImpl->m_aMutex ); + m_pImpl->m_bAfterLast = true; + m_pImpl->m_xDataSupplier->validate(); + return false; + } + } + + // unreachable... +} + + +// virtual +sal_Bool SAL_CALL ResultSet::previous() +{ +/* + previous() is not the same as relative( -1 ) because it makes sense + to call previous() when there is no current row. +*/ + std::unique_lock aGuard( m_pImpl->m_aMutex ); + + if ( m_pImpl->m_bAfterLast ) + { + m_pImpl->m_bAfterLast = false; + sal_Int32 nCount = m_pImpl->m_xDataSupplier->totalCount(); + m_pImpl->m_nPos = nCount; + } + else if ( m_pImpl->m_nPos ) + m_pImpl->m_nPos--; + + if ( m_pImpl->m_nPos ) + { + m_pImpl->m_xDataSupplier->validate(); + return true; + } + + m_pImpl->m_xDataSupplier->validate(); + return false; +} + + +// virtual +void SAL_CALL ResultSet::refreshRow() +{ + std::unique_lock aGuard( m_pImpl->m_aMutex ); + if ( m_pImpl->m_bAfterLast || ( m_pImpl->m_nPos == 0 ) ) + return; + + m_pImpl->m_xDataSupplier->releasePropertyValues( m_pImpl->m_nPos ); + m_pImpl->m_xDataSupplier->validate(); +} + + +// virtual +sal_Bool SAL_CALL ResultSet::rowUpdated() +{ + m_pImpl->m_xDataSupplier->validate(); + return false; +} + + +// virtual +sal_Bool SAL_CALL ResultSet::rowInserted() +{ + m_pImpl->m_xDataSupplier->validate(); + return false; +} + + +// virtual +sal_Bool SAL_CALL ResultSet::rowDeleted() +{ + m_pImpl->m_xDataSupplier->validate(); + return false; +} + + +// virtual +uno::Reference< uno::XInterface > SAL_CALL ResultSet::getStatement() +{ +/* + returns the Statement that produced this ResultSet object. If the + result set was generated some other way, ... this method returns null. +*/ + m_pImpl->m_xDataSupplier->validate(); + return uno::Reference< uno::XInterface >(); +} + + +// XRow methods. + + +// virtual +sal_Bool SAL_CALL ResultSet::wasNull() +{ + // This method can not be implemented correctly!!! Imagine different + // threads doing a getXYZ - wasNull calling sequence on the same + // implementation object... + + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_xDataSupplier->validate(); + return xValues->wasNull(); + } + } + + m_pImpl->m_xDataSupplier->validate(); + return m_pImpl->m_bWasNull; +} + + +// virtual +OUString SAL_CALL ResultSet::getString( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getString( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return OUString(); +} + + +// virtual +sal_Bool SAL_CALL ResultSet::getBoolean( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getBoolean( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return false; +} + + +// virtual +sal_Int8 SAL_CALL ResultSet::getByte( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getByte( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return 0; +} + + +// virtual +sal_Int16 SAL_CALL ResultSet::getShort( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getShort( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return 0; +} + + +// virtual +sal_Int32 SAL_CALL ResultSet::getInt( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getInt( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return 0; +} + + +// virtual +sal_Int64 SAL_CALL ResultSet::getLong( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getLong( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return 0; +} + + +// virtual +float SAL_CALL ResultSet::getFloat( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getFloat( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return 0; +} + + +// virtual +double SAL_CALL ResultSet::getDouble( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getDouble( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return 0; +} + + +// virtual +uno::Sequence< sal_Int8 > SAL_CALL +ResultSet::getBytes( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getBytes( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return uno::Sequence< sal_Int8 >(); +} + + +// virtual +util::Date SAL_CALL ResultSet::getDate( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getDate( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return util::Date(); +} + + +// virtual +util::Time SAL_CALL ResultSet::getTime( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getTime( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return util::Time(); +} + + +// virtual +util::DateTime SAL_CALL +ResultSet::getTimestamp( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getTimestamp( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return util::DateTime(); +} + + +// virtual +uno::Reference< io::XInputStream > SAL_CALL +ResultSet::getBinaryStream( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getBinaryStream( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return uno::Reference< io::XInputStream >(); +} + + +// virtual +uno::Reference< io::XInputStream > SAL_CALL +ResultSet::getCharacterStream( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getCharacterStream( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return uno::Reference< io::XInputStream >(); +} + + +// virtual +uno::Any SAL_CALL ResultSet::getObject( + sal_Int32 columnIndex, + const uno::Reference< container::XNameAccess >& typeMap ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getObject( columnIndex, typeMap ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return uno::Any(); +} + + +// virtual +uno::Reference< sdbc::XRef > SAL_CALL +ResultSet::getRef( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getRef( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return uno::Reference< sdbc::XRef >(); +} + + +// virtual +uno::Reference< sdbc::XBlob > SAL_CALL +ResultSet::getBlob( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getBlob( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return uno::Reference< sdbc::XBlob >(); +} + + +// virtual +uno::Reference< sdbc::XClob > SAL_CALL +ResultSet::getClob( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getClob( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return uno::Reference< sdbc::XClob >(); +} + + +// virtual +uno::Reference< sdbc::XArray > SAL_CALL +ResultSet::getArray( sal_Int32 columnIndex ) +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + { + uno::Reference< sdbc::XRow > xValues + = m_pImpl->m_xDataSupplier->queryPropertyValues( + m_pImpl->m_nPos - 1 ); + if ( xValues.is() ) + { + m_pImpl->m_bWasNull = false; + m_pImpl->m_xDataSupplier->validate(); + return xValues->getArray( columnIndex ); + } + } + + m_pImpl->m_bWasNull = true; + m_pImpl->m_xDataSupplier->validate(); + return uno::Reference< sdbc::XArray >(); +} + + +// XCloseable methods. + + +// virtual +void SAL_CALL ResultSet::close() +{ + m_pImpl->m_xDataSupplier->close(); + m_pImpl->m_xDataSupplier->validate(); +} + + +// XContentAccess methods. + + +// virtual +OUString SAL_CALL ResultSet::queryContentIdentifierString() +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + return m_pImpl->m_xDataSupplier->queryContentIdentifierString( + m_pImpl->m_nPos - 1 ); + + return OUString(); +} + + +// virtual +uno::Reference< css::ucb::XContentIdentifier > SAL_CALL +ResultSet::queryContentIdentifier() +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + return m_pImpl->m_xDataSupplier->queryContentIdentifier( + m_pImpl->m_nPos - 1 ); + + return uno::Reference< css::ucb::XContentIdentifier >(); +} + + +// virtual +uno::Reference< css::ucb::XContent > SAL_CALL +ResultSet::queryContent() +{ + if ( m_pImpl->m_nPos && !m_pImpl->m_bAfterLast ) + return m_pImpl->m_xDataSupplier->queryContent( m_pImpl->m_nPos - 1 ); + + return uno::Reference< css::ucb::XContent >(); +} + + +// XPropertySet methods. + + +// virtual +uno::Reference< beans::XPropertySetInfo > SAL_CALL +ResultSet::getPropertySetInfo() +{ + std::unique_lock aGuard( m_pImpl->m_aMutex ); + + if ( !m_pImpl->m_xPropSetInfo.is() ) + m_pImpl->m_xPropSetInfo + = new PropertySetInfo( aPropertyTable, + RESULTSET_PROPERTY_COUNT ); + return m_pImpl->m_xPropSetInfo; +} + + +// virtual +void SAL_CALL ResultSet::setPropertyValue( const OUString& aPropertyName, + const uno::Any& ) +{ + if ( aPropertyName == "RowCount" ) + { + // property is read-only. + throw lang::IllegalArgumentException(); + } + else if ( aPropertyName == "IsRowCountFinal" ) + { + // property is read-only. + throw lang::IllegalArgumentException(); + } + else + { + throw beans::UnknownPropertyException(aPropertyName); + } +} + + +// virtual +uno::Any SAL_CALL ResultSet::getPropertyValue( + const OUString& PropertyName ) +{ + uno::Any aValue; + + if ( PropertyName == "RowCount" ) + { + aValue <<= m_pImpl->m_xDataSupplier->currentCount(); + } + else if ( PropertyName == "IsRowCountFinal" ) + { + aValue <<= m_pImpl->m_xDataSupplier->isCountFinal(); + } + else + { + throw beans::UnknownPropertyException(PropertyName); + } + + return aValue; +} + + +// virtual +void SAL_CALL ResultSet::addPropertyChangeListener( + const OUString& aPropertyName, + const uno::Reference< beans::XPropertyChangeListener >& xListener ) +{ + // Note: An empty property name means a listener for "all" properties. + + std::unique_lock aGuard( m_pImpl->m_aMutex ); + + if ( !aPropertyName.isEmpty() && + aPropertyName != "RowCount" && + aPropertyName != "IsRowCountFinal" ) + throw beans::UnknownPropertyException(aPropertyName); + + if ( !m_pImpl->m_pPropertyChangeListeners ) + m_pImpl->m_pPropertyChangeListeners.reset( + new PropertyChangeListeners()); + + m_pImpl->m_pPropertyChangeListeners->addInterface(aGuard, + aPropertyName, xListener ); +} + + +// virtual +void SAL_CALL ResultSet::removePropertyChangeListener( + const OUString& aPropertyName, + const uno::Reference< beans::XPropertyChangeListener >& xListener ) +{ + std::unique_lock aGuard( m_pImpl->m_aMutex ); + + if ( !aPropertyName.isEmpty() && + aPropertyName != "RowCount" && + aPropertyName != "IsRowCountFinal" ) + throw beans::UnknownPropertyException(aPropertyName); + + if ( m_pImpl->m_pPropertyChangeListeners ) + m_pImpl->m_pPropertyChangeListeners->removeInterface(aGuard, + aPropertyName, xListener ); + +} + + +// virtual +void SAL_CALL ResultSet::addVetoableChangeListener( + const OUString&, + const uno::Reference< beans::XVetoableChangeListener >& ) +{ + // No constrained props, at the moment. +} + + +// virtual +void SAL_CALL ResultSet::removeVetoableChangeListener( + const OUString&, + const uno::Reference< beans::XVetoableChangeListener >& ) +{ + // No constrained props, at the moment. +} + + +// Non-interface methods. + + +void ResultSet::propertyChanged( const beans::PropertyChangeEvent& rEvt ) const +{ + std::unique_lock aGuard( m_pImpl->m_aMutex ); + + if ( !m_pImpl->m_pPropertyChangeListeners ) + return; + + // Notify listeners interested especially in the changed property. + comphelper::OInterfaceContainerHelper4<beans::XPropertyChangeListener>* pPropsContainer + = m_pImpl->m_pPropertyChangeListeners->getContainer( + rEvt.PropertyName ); + if ( pPropsContainer ) + { + pPropsContainer->notifyEach(aGuard, &beans::XPropertyChangeListener::propertyChange, rEvt); + } + + // Notify listeners interested in all properties. + pPropsContainer + = m_pImpl->m_pPropertyChangeListeners->getContainer( OUString() ); + if ( pPropsContainer ) + { + comphelper::OInterfaceIteratorHelper4 aIter( aGuard, *pPropsContainer ); + while ( aIter.hasMoreElements() ) + { + aIter.next()->propertyChange( rEvt ); + } + } +} + + +void ResultSet::rowCountChanged( sal_uInt32 nOld, sal_uInt32 nNew ) +{ + OSL_ENSURE( nOld < nNew, "ResultSet::rowCountChanged - nOld >= nNew!" ); + + if ( !m_pImpl->m_pPropertyChangeListeners ) + return; + + propertyChanged( + beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >( this ), + "RowCount", + false, + 1001, + uno::Any( nOld ), // old value + uno::Any( nNew ) ) ); // new value +} + + +void ResultSet::rowCountFinal() +{ + if ( !m_pImpl->m_pPropertyChangeListeners ) + return; + + propertyChanged( + beans::PropertyChangeEvent( + static_cast< cppu::OWeakObject * >( this ), + "IsRowCountFinal", + false, + 1000, + uno:: Any( false ), // old value + uno::Any( true ) ) ); // new value +} + + +const uno::Sequence< beans::Property >& ResultSet::getProperties() const +{ + return m_pImpl->m_aProperties; +} + + +const uno::Reference< css::ucb::XCommandEnvironment >& +ResultSet::getEnvironment() const +{ + return m_pImpl->m_xEnv; +} + +} // namespace ucbhelper + +namespace ucbhelper_impl { + + +// PropertySetInfo Implementation. + + +PropertySetInfo::PropertySetInfo( + const PropertyInfo* pProps, + sal_Int32 nProps ) + : m_aProps( nProps ) +{ + + if ( !nProps ) + return; + + const PropertyInfo* pEntry = pProps; + beans::Property* pProperties = m_aProps.getArray(); + + for ( sal_Int32 n = 0; n < nProps; ++n ) + { + beans::Property& rProp = pProperties[ n ]; + + rProp.Name = OUString::createFromAscii( pEntry->pName ); + rProp.Handle = pEntry->nHandle; + rProp.Type = pEntry->pGetCppuType(); + rProp.Attributes = pEntry->nAttributes; + + pEntry++; + } +} + + + +// XInterface methods. +void SAL_CALL PropertySetInfo::acquire() + noexcept +{ + OWeakObject::acquire(); +} + +void SAL_CALL PropertySetInfo::release() + noexcept +{ + OWeakObject::release(); +} + +css::uno::Any SAL_CALL PropertySetInfo::queryInterface( + const css::uno::Type & rType ) +{ + css::uno::Any aRet = cppu::queryInterface( rType, + static_cast< lang::XTypeProvider* >(this), + static_cast< beans::XPropertySetInfo* >(this) + ); + return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); +} + +// XTypeProvider methods. + + +XTYPEPROVIDER_IMPL_2( PropertySetInfo, + lang::XTypeProvider, + beans::XPropertySetInfo ); + + +// XPropertySetInfo methods. + + +// virtual +uno::Sequence< beans::Property > SAL_CALL PropertySetInfo::getProperties() +{ + return m_aProps; +} + + +// virtual +beans::Property SAL_CALL PropertySetInfo::getPropertyByName( + const OUString& aName ) +{ + beans::Property aProp; + if ( queryProperty( aName, aProp ) ) + return aProp; + + throw beans::UnknownPropertyException(aName); +} + + +// virtual +sal_Bool SAL_CALL PropertySetInfo::hasPropertyByName( + const OUString& Name ) +{ + beans::Property aProp; + return queryProperty( Name, aProp ); +} + + +bool PropertySetInfo::queryProperty( + std::u16string_view aName, beans::Property& rProp ) const +{ + sal_Int32 nCount = m_aProps.getLength(); + const beans::Property* pProps = m_aProps.getConstArray(); + for ( sal_Int32 n = 0; n < nCount; ++n ) + { + const beans::Property& rCurr = pProps[ n ]; + if ( rCurr.Name == aName ) + { + rProp = rCurr; + return true; + } + } + + return false; +} + +} // namespace ucbhelper_impl + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |