From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- dbaccess/source/core/dataaccess/connection.cxx | 808 +++++++++++++++++++++++++ 1 file changed, 808 insertions(+) create mode 100644 dbaccess/source/core/dataaccess/connection.cxx (limited to 'dbaccess/source/core/dataaccess/connection.cxx') diff --git a/dbaccess/source/core/dataaccess/connection.cxx b/dbaccess/source/core/dataaccess/connection.cxx new file mode 100644 index 000000000..37cf9e669 --- /dev/null +++ b/dbaccess/source/core/dataaccess/connection.cxx @@ -0,0 +1,808 @@ +/* -*- 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 + +#include + +#include "connection.hxx" +#include "datasource.hxx" +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::sdb; +using namespace ::com::sun::star::sdb::application; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::reflection; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::graphic; +using namespace ::osl; +using namespace ::comphelper; +using namespace ::cppu; +using namespace ::dbtools; + +using ::com::sun::star::sdb::tools::XTableName; +using ::com::sun::star::sdb::tools::XObjectNames; +using ::com::sun::star::sdb::tools::XDataSourceMetaData; + +namespace dbaccess +{ + +// XServiceInfo +OUString OConnection::getImplementationName( ) +{ + return "com.sun.star.comp.dbaccess.Connection"; +} + +sal_Bool OConnection::supportsService( const OUString& _rServiceName ) +{ + return cppu::supportsService(this, _rServiceName); +} + +Sequence< OUString > OConnection::getSupportedServiceNames( ) +{ + Sequence< OUString > aSupported = OConnectionWrapper::getSupportedServiceNames(); + + if ( comphelper::findValue( aSupported, SERVICE_SDB_CONNECTION ) == -1 ) + { + sal_Int32 nLen = aSupported.getLength(); + aSupported.realloc( nLen + 1 ); + aSupported.getArray()[ nLen ] = SERVICE_SDB_CONNECTION; + } + + return aSupported; +} + +// XCloseable +void OConnection::close() +{ + // being closed is the same as being disposed + dispose(); +} + +sal_Bool OConnection::isClosed() +{ + MutexGuard aGuard(m_aMutex); + return !m_xMasterConnection.is(); +} + +// XConnection +Reference< XStatement > OConnection::createStatement() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + Reference< XStatement > xStatement; + Reference< XStatement > xMasterStatement = m_xMasterConnection->createStatement(); + if ( xMasterStatement.is() ) + { + xStatement = new OStatement(this, xMasterStatement); + m_aStatements.emplace_back(xStatement); + } + return xStatement; +} + +Reference< XPreparedStatement > OConnection::prepareStatement(const OUString& sql) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + // TODO convert the SQL to SQL the driver understands + Reference< XPreparedStatement > xStatement; + Reference< XPreparedStatement > xMasterStatement = m_xMasterConnection->prepareStatement(sql); + if ( xMasterStatement.is() ) + { + xStatement = new OPreparedStatement(this, xMasterStatement); + m_aStatements.emplace_back(xStatement); + } + return xStatement; +} + +Reference< XPreparedStatement > OConnection::prepareCall(const OUString& sql) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + Reference< XPreparedStatement > xStatement; + Reference< XPreparedStatement > xMasterStatement = m_xMasterConnection->prepareCall(sql); + if ( xMasterStatement.is() ) + { + xStatement = new OCallableStatement(this, xMasterStatement); + m_aStatements.emplace_back(xStatement); + } + return xStatement; +} + +OUString OConnection::nativeSQL(const OUString& sql) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_xMasterConnection->nativeSQL(sql); +} + +void OConnection::setAutoCommit(sal_Bool autoCommit) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + m_xMasterConnection->setAutoCommit(autoCommit); +} + +sal_Bool OConnection::getAutoCommit() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_xMasterConnection->getAutoCommit(); +} + +void OConnection::commit() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + m_xMasterConnection->commit(); +} + +void OConnection::rollback() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + m_xMasterConnection->rollback(); +} + +Reference< XDatabaseMetaData > OConnection::getMetaData() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_xMasterConnection->getMetaData(); +} + +void OConnection::setReadOnly(sal_Bool readOnly) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + m_xMasterConnection->setReadOnly(readOnly); +} + +sal_Bool OConnection::isReadOnly() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_xMasterConnection->isReadOnly(); +} + +void OConnection::setCatalog(const OUString& catalog) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + m_xMasterConnection->setCatalog(catalog); +} + +OUString OConnection::getCatalog() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_xMasterConnection->getCatalog(); +} + +void OConnection::setTransactionIsolation(sal_Int32 level) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + m_xMasterConnection->setTransactionIsolation(level); +} + +sal_Int32 OConnection::getTransactionIsolation() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_xMasterConnection->getTransactionIsolation(); +} + +Reference< XNameAccess > OConnection::getTypeMap() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_xMasterConnection->getTypeMap(); +} + +void OConnection::setTypeMap(const Reference< XNameAccess > & typeMap) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + m_xMasterConnection->setTypeMap(typeMap); +} + +// OConnection + +OConnection::OConnection(ODatabaseSource& _rDB + , Reference< XConnection > const & _rxMaster + , const Reference< XComponentContext >& _rxORB) + :OSubComponent(m_aMutex, static_cast< OWeakObject* >(&_rDB)) + // as the queries reroute their refcounting to us, this m_aMutex is okey. If the queries + // container would do its own refcounting, it would have to acquire m_pMutex + // same for tables + ,m_aTableFilter(_rDB.m_pImpl->m_aTableFilter) + ,m_aTableTypeFilter(_rDB.m_pImpl->m_aTableTypeFilter) + ,m_aContext( _rxORB ) + ,m_xMasterConnection(_rxMaster) + ,m_aWarnings( Reference< XWarningsSupplier >( _rxMaster, UNO_QUERY ) ) + ,m_nInAppend(0) + ,m_bSupportsViews(false) + ,m_bSupportsUsers(false) + ,m_bSupportsGroups(false) +{ + osl_atomic_increment(&m_refCount); + + try + { + Reference< XProxyFactory > xProxyFactory = ProxyFactory::create( m_aContext ); + Reference xAgg = xProxyFactory->createProxy(_rxMaster); + setDelegation(xAgg,m_refCount); + OSL_ENSURE(m_xConnection.is(), "OConnection::OConnection : invalid master connection !"); + } + catch(const Exception&) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + + m_xTableUIProvider.set(m_xMasterConnection, css::uno::UNO_QUERY); + + try + { + m_xQueries = OQueryContainer::create(Reference< XNameContainer >(_rDB.getQueryDefinitions(), UNO_QUERY), this, _rxORB, &m_aWarnings).get(); + + bool bCase = true; + Reference xMeta; + try + { + xMeta = getMetaData(); + bCase = xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(); + } + catch(const SQLException&) + { + } + Reference< XNameContainer > xTableDefinitions(_rDB.getTables(),UNO_QUERY); + m_pTables.reset( new OTableContainer( *this, m_aMutex, this, bCase, xTableDefinitions, this, m_nInAppend ) ); + + // check if we support types + if ( xMeta.is() ) + { + Reference xRes = xMeta->getTableTypes(); + if(xRes.is()) + { + Reference xRow(xRes,UNO_QUERY); + while(xRes->next()) + { + OUString sValue = xRow->getString(1); + if( !xRow->wasNull() && sValue == "VIEW") + { + m_bSupportsViews = true; + break; + } + } + } + // some dbs don't support this type so we should ask if a XViewsSupplier is supported + if(!m_bSupportsViews) + { + Reference< XViewsSupplier > xMaster(getMasterTables(),UNO_QUERY); + + if (xMaster.is() && xMaster->getViews().is()) + m_bSupportsViews = true; + } + if(m_bSupportsViews) + { + m_pViews.reset( new OViewContainer(*this, m_aMutex, this, bCase, this, m_nInAppend) ); + m_pViews->addContainerListener(m_pTables.get()); + m_pTables->addContainerListener(m_pViews.get()); + } + m_bSupportsUsers = Reference< XUsersSupplier> (getMasterTables(),UNO_QUERY).is(); + m_bSupportsGroups = Reference< XGroupsSupplier> (getMasterTables(),UNO_QUERY).is(); + + impl_checkTableQueryNames_nothrow(); + } + } + catch(const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } + osl_atomic_decrement( &m_refCount ); +} + +OConnection::~OConnection() +{ +} + +// XWarningsSupplier +Any SAL_CALL OConnection::getWarnings() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_aWarnings.getWarnings(); +} + +void SAL_CALL OConnection::clearWarnings( ) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + m_aWarnings.clearWarnings(); +} + +namespace +{ + struct CompareTypeByName + { + bool operator() ( const Type& _rLHS, const Type& _rRHS ) const + { + return _rLHS.getTypeName() < _rRHS.getTypeName(); + } + }; + typedef std::set< Type, CompareTypeByName > TypeBag; + + void lcl_copyTypes( TypeBag& _out_rTypes, const Sequence< Type >& _rTypes ) + { + std::copy( _rTypes.begin(), _rTypes.end(), + std::insert_iterator< TypeBag >( _out_rTypes, _out_rTypes.begin() ) ); + } +} + +// css::lang::XTypeProvider +Sequence< Type > OConnection::getTypes() +{ + TypeBag aNormalizedTypes; + + lcl_copyTypes( aNormalizedTypes, OSubComponent::getTypes() ); + lcl_copyTypes( aNormalizedTypes, OConnection_Base::getTypes() ); + lcl_copyTypes( aNormalizedTypes, ::connectivity::OConnectionWrapper::getTypes() ); + + if ( !m_bSupportsViews ) + aNormalizedTypes.erase( cppu::UnoType::get() ); + if ( !m_bSupportsUsers ) + aNormalizedTypes.erase( cppu::UnoType::get() ); + if ( !m_bSupportsGroups ) + aNormalizedTypes.erase( cppu::UnoType::get() ); + + return comphelper::containerToSequence(aNormalizedTypes); +} + +Sequence< sal_Int8 > OConnection::getImplementationId() +{ + return css::uno::Sequence(); +} + +// css::uno::XInterface +Any OConnection::queryInterface( const Type & rType ) +{ + if ( !m_bSupportsViews && rType.equals( cppu::UnoType::get() ) ) + return Any(); + else if ( !m_bSupportsUsers && rType.equals( cppu::UnoType::get() ) ) + return Any(); + else if ( !m_bSupportsGroups && rType.equals( cppu::UnoType::get() ) ) + return Any(); + Any aReturn = OSubComponent::queryInterface( rType ); + if (!aReturn.hasValue()) + { + aReturn = OConnection_Base::queryInterface( rType ); + if (!aReturn.hasValue()) + aReturn = OConnectionWrapper::queryInterface( rType ); + } + return aReturn; +} + +void OConnection::acquire() noexcept +{ + // include this one when you want to see who calls it (call graph) + OSubComponent::acquire(); +} + +void OConnection::release() noexcept +{ + // include this one when you want to see who calls it (call graph) + OSubComponent::release(); +} + +// OSubComponent +void OConnection::disposing() +{ + MutexGuard aGuard(m_aMutex); + + OSubComponent::disposing(); + OConnectionWrapper::disposing(); + + for (auto const& statement : m_aStatements) + { + Reference xComp(statement.get(),UNO_QUERY); + ::comphelper::disposeComponent(xComp); + } + m_aStatements.clear(); + m_xMasterTables = nullptr; + + if(m_pTables) + m_pTables->dispose(); + if(m_pViews) + m_pViews->dispose(); + + ::comphelper::disposeComponent(m_xQueries); + + for (auto const& composer : m_aComposers) + { + Reference xComp(composer.get(),UNO_QUERY); + ::comphelper::disposeComponent(xComp); + } + + m_aComposers.clear(); + + try + { + if (m_xMasterConnection.is()) + m_xMasterConnection->close(); + } + catch(const Exception&) + { + } + m_xMasterConnection = nullptr; +} + +// XChild +Reference< XInterface > OConnection::getParent() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + return m_xParent; +} + +void OConnection::setParent(const Reference< XInterface > & /*Parent*/) +{ + throw NoSupportException(); +} + +// XSQLQueryComposerFactory +Reference< XSQLQueryComposer > OConnection::createQueryComposer() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + // Reference< XNumberFormatsSupplier > xSupplier = pParent->getNumberFormatsSupplier(); + Reference< XSQLQueryComposer > xComposer( new OQueryComposer( this ) ); + m_aComposers.emplace_back(xComposer); + return xComposer; +} + +void OConnection::impl_fillTableFilter() +{ + Reference xProp(getParent(),UNO_QUERY); + if ( xProp.is() ) + { + xProp->getPropertyValue(PROPERTY_TABLEFILTER) >>= m_aTableFilter; + xProp->getPropertyValue(PROPERTY_TABLETYPEFILTER) >>= m_aTableTypeFilter; + } +} + +void OConnection::refresh(const Reference< XNameAccess >& _rToBeRefreshed) +{ + if ( _rToBeRefreshed == Reference< XNameAccess >(m_pTables.get()) ) + { + if (m_pTables && !m_pTables->isInitialized()) + { + impl_fillTableFilter(); + // check if our "master connection" can supply tables + getMasterTables(); + + if (m_xMasterTables.is() && m_xMasterTables->getTables().is()) + { // yes -> wrap them + m_pTables->construct(m_xMasterTables->getTables(),m_aTableFilter, m_aTableTypeFilter); + } + else + { // no -> use an own container + m_pTables->construct(m_aTableFilter, m_aTableTypeFilter); + } + } + } + else if ( _rToBeRefreshed == Reference< XNameAccess >(m_pViews.get()) ) + { + if (m_pViews && !m_pViews->isInitialized()) + { + impl_fillTableFilter(); + // check if our "master connection" can supply tables + Reference< XViewsSupplier > xMaster(getMasterTables(),UNO_QUERY); + + if (xMaster.is() && xMaster->getViews().is()) + m_pViews->construct(xMaster->getViews(),m_aTableFilter, m_aTableTypeFilter); + else + m_pViews->construct(m_aTableFilter, m_aTableTypeFilter); + } + } +} + +// XTablesSupplier +Reference< XNameAccess > OConnection::getTables() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + refresh(m_pTables.get()); + + return m_pTables.get(); +} + +Reference< XNameAccess > SAL_CALL OConnection::getViews( ) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + refresh(m_pViews.get()); + + return m_pViews.get(); +} + +// XQueriesSupplier +Reference< XNameAccess > OConnection::getQueries() +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + return m_xQueries; +} + +// css::sdb::XCommandPreparation +Reference< XPreparedStatement > SAL_CALL OConnection::prepareCommand( const OUString& command, sal_Int32 commandType ) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + OUString aStatement; + switch (commandType) + { + case CommandType::TABLE: + { + aStatement = "SELECT * FROM "; + + OUString sCatalog, sSchema, sTable; + ::dbtools::qualifiedNameComponents( getMetaData(), command, sCatalog, sSchema, sTable, ::dbtools::EComposeRule::InDataManipulation ); + aStatement += ::dbtools::composeTableNameForSelect( this, sCatalog, sSchema, sTable ); + } + break; + case CommandType::QUERY: + if ( m_xQueries->hasByName(command) ) + { + Reference< XPropertySet > xQuery(m_xQueries->getByName(command),UNO_QUERY); + xQuery->getPropertyValue(PROPERTY_COMMAND) >>= aStatement; + } + break; + default: + aStatement = command; + } + // TODO EscapeProcessing + return prepareStatement(aStatement); +} + +Reference< XInterface > SAL_CALL OConnection::createInstance( const OUString& _sServiceSpecifier ) +{ + Reference< XServiceInfo > xRet; + if ( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER == _sServiceSpecifier || _sServiceSpecifier == "com.sun.star.sdb.SingleSelectQueryAnalyzer" ) + { + xRet = new OSingleSelectQueryComposer( getTables(),this, m_aContext ); + m_aComposers.emplace_back(xRet); + } + else + { + if ( !_sServiceSpecifier.isEmpty() ) + { + TSupportServices::const_iterator aFind = m_aSupportServices.find(_sServiceSpecifier); + if ( aFind == m_aSupportServices.end() ) + { + Reference xMy(this); + Sequence aArgs{ Any(NamedValue("ActiveConnection",Any(xMy))) }; + aFind = m_aSupportServices.emplace( + _sServiceSpecifier, + m_aContext->getServiceManager()->createInstanceWithArgumentsAndContext(_sServiceSpecifier, aArgs, m_aContext) + ).first; + } + return aFind->second; + } + } + return Reference(xRet, UNO_QUERY); +} + +Reference< XInterface > SAL_CALL OConnection::createInstanceWithArguments( const OUString& _sServiceSpecifier, const Sequence< Any >& /*Arguments*/ ) +{ + return createInstance(_sServiceSpecifier); +} + +Sequence< OUString > SAL_CALL OConnection::getAvailableServiceNames( ) +{ + Sequence< OUString > aRet { SERVICE_NAME_SINGLESELECTQUERYCOMPOSER }; + return aRet; +} + +Reference< XTablesSupplier > const & OConnection::getMasterTables() +{ +// check if out "master connection" can supply tables + if(!m_xMasterTables.is()) + { + try + { + Reference xMeta = getMetaData(); + if ( xMeta.is() ) + m_xMasterTables = ::dbtools::getDataDefinitionByURLAndConnection( xMeta->getURL(), m_xMasterConnection, m_aContext ); + } + catch(const SQLException&) + { + } + } + return m_xMasterTables; +} + +// XUsersSupplier +Reference< XNameAccess > SAL_CALL OConnection::getUsers( ) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + + Reference xUsr(getMasterTables(),UNO_QUERY); + return xUsr.is() ? xUsr->getUsers() : Reference< XNameAccess >(); +} + +// XGroupsSupplier +Reference< XNameAccess > SAL_CALL OConnection::getGroups( ) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + Reference xGrp(getMasterTables(),UNO_QUERY); + return xGrp.is() ? xGrp->getGroups() : Reference< XNameAccess >(); +} + +void OConnection::impl_loadConnectionTools_throw() +{ + m_xConnectionTools = css::sdb::tools::ConnectionTools::createWithConnection( m_aContext, this ); +} + +Reference< XTableName > SAL_CALL OConnection::createTableName( ) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + impl_loadConnectionTools_throw(); + + return m_xConnectionTools->createTableName(); +} + +Reference< XObjectNames > SAL_CALL OConnection::getObjectNames( ) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + impl_loadConnectionTools_throw(); + + return m_xConnectionTools->getObjectNames(); +} + +Reference< XDataSourceMetaData > SAL_CALL OConnection::getDataSourceMetaData( ) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + impl_loadConnectionTools_throw(); + + return m_xConnectionTools->getDataSourceMetaData(); +} + +Reference< css::container::XNameAccess > SAL_CALL OConnection::getFieldsByCommandDescriptor( ::sal_Int32 commandType, const OUString& command, css::uno::Reference< css::lang::XComponent >& keepFieldsAlive ) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + impl_loadConnectionTools_throw(); + + return m_xConnectionTools->getFieldsByCommandDescriptor(commandType,command,keepFieldsAlive); +} + +Reference< XSingleSelectQueryComposer > SAL_CALL OConnection::getComposer( ::sal_Int32 commandType, const OUString& command ) +{ + MutexGuard aGuard(m_aMutex); + checkDisposed(); + impl_loadConnectionTools_throw(); + + return m_xConnectionTools->getComposer(commandType,command); +} + +void OConnection::impl_checkTableQueryNames_nothrow() +{ + DatabaseMetaData aMeta( static_cast< XConnection* >( this ) ); + if ( !aMeta.supportsSubqueriesInFrom() ) + // nothing to do + return; + + try + { + Reference< XNameAccess > xTables( getTables() ); + const Sequence< OUString > aTableNames( xTables->getElementNames() ); + std::set< OUString > aSortedTableNames( aTableNames.begin(), aTableNames.end() ); + + Reference< XNameAccess > xQueries( getQueries() ); + const Sequence< OUString > aQueryNames( xQueries->getElementNames() ); + + for ( auto const & queryName : aQueryNames ) + { + if ( aSortedTableNames.find( queryName ) != aSortedTableNames.end() ) + { + OUString sConflictWarning( DBA_RES( RID_STR_CONFLICTING_NAMES ) ); + m_aWarnings.appendWarning( sConflictWarning, "01SB0", *this ); + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION("dbaccess"); + } +} + +Reference< XGraphic > SAL_CALL OConnection::getTableIcon( const OUString& TableName, ::sal_Int32 ColorMode ) +{ + Reference< XGraphic > xReturn; + + // ask our aggregate + if ( m_xTableUIProvider.is() ) + xReturn = m_xTableUIProvider->getTableIcon( TableName, ColorMode ); + + // ask ourself + // well, we don't have own functionality here ... + // In the future, we might decide to delegate the complete handling to this interface. + // In this case, we would need to load the icon here. + + return xReturn; +} + +Reference< XInterface > SAL_CALL OConnection::getTableEditor( const Reference< XDatabaseDocumentUI >& DocumentUI, const OUString& TableName ) +{ + Reference< XInterface > xReturn; + + // ask our aggregate + if ( m_xTableUIProvider.is() ) + xReturn = m_xTableUIProvider->getTableEditor( DocumentUI, TableName ); + + // ask ourself + // well, we don't have own functionality here ... + // In the future, we might decide to delegate the complete handling to this interface. + // In this case, we would need to instantiate a css.sdb.TableDesign here. + + return xReturn; +} + +} // namespace dbaccess + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3