| /************************************************************** |
| * |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #include "dbu_reghelper.hxx" |
| #include "dbu_resource.hrc" |
| #include "dbu_uno.hrc" |
| #include "dbustrings.hrc" |
| #include "moduledbu.hxx" |
| #include "sqlmessage.hxx" |
| #include "WCopyTable.hxx" |
| |
| /** === begin UNO includes === **/ |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
| #include <com/sun/star/sdb/application/XCopyTableWizard.hpp> |
| #include <com/sun/star/sdb/application/CopyTableContinuation.hpp> |
| #include <com/sun/star/sdb/application/CopyTableOperation.hpp> |
| #include <com/sun/star/ucb/AlreadyInitializedException.hpp> |
| #include <com/sun/star/lang/NotInitializedException.hpp> |
| #include <com/sun/star/sdbc/XDataSource.hpp> |
| #include <com/sun/star/sdbc/DataType.hpp> |
| #include <com/sun/star/container/XNameAccess.hpp> |
| #include <com/sun/star/container/XChild.hpp> |
| #include <com/sun/star/task/XInteractionHandler.hpp> |
| #include <com/sun/star/frame/XModel.hpp> |
| #include <com/sun/star/sdb/XDocumentDataSource.hpp> |
| #include <com/sun/star/sdb/XCompletedConnection.hpp> |
| #include <com/sun/star/sdb/CommandType.hpp> |
| #include <com/sun/star/sdbcx/XTablesSupplier.hpp> |
| #include <com/sun/star/sdb/XQueriesSupplier.hpp> |
| #include <com/sun/star/lang/DisposedException.hpp> |
| #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> |
| #include <com/sun/star/sdbc/XParameters.hpp> |
| #include <com/sun/star/sdbc/XRow.hpp> |
| #include <com/sun/star/sdbc/XBlob.hpp> |
| #include <com/sun/star/sdbc/XClob.hpp> |
| #include <com/sun/star/sdbcx/XRowLocate.hpp> |
| #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp> |
| #include <com/sun/star/sdb/SQLContext.hpp> |
| #include <com/sun/star/sdbc/XDriverManager.hpp> |
| /** === end UNO includes === **/ |
| |
| #include <comphelper/componentcontext.hxx> |
| #include <comphelper/interaction.hxx> |
| #include <comphelper/namedvaluecollection.hxx> |
| #include <comphelper/proparrhlp.hxx> |
| #include <comphelper/string.hxx> |
| #include <connectivity/dbexception.hxx> |
| #include <connectivity/dbtools.hxx> |
| #include <cppuhelper/exc_hlp.hxx> |
| #include <cppuhelper/implbase1.hxx> |
| #include <rtl/ustrbuf.hxx> |
| #include <rtl/logfile.hxx> |
| #include <svtools/genericunodialog.hxx> |
| #include <tools/diagnose_ex.h> |
| #include <unotools/sharedunocomponent.hxx> |
| #include <vcl/msgbox.hxx> |
| #include <vcl/waitobj.hxx> |
| |
| //........................................................................ |
| namespace dbaui |
| { |
| //........................................................................ |
| |
| /** === begin UNO using === **/ |
| using ::com::sun::star::uno::Reference; |
| using ::com::sun::star::uno::XInterface; |
| using ::com::sun::star::uno::UNO_QUERY; |
| using ::com::sun::star::uno::UNO_QUERY_THROW; |
| using ::com::sun::star::uno::UNO_SET_THROW; |
| using ::com::sun::star::uno::Exception; |
| using ::com::sun::star::uno::RuntimeException; |
| using ::com::sun::star::uno::Any; |
| using ::com::sun::star::uno::makeAny; |
| using ::com::sun::star::uno::Sequence; |
| using ::com::sun::star::beans::XPropertySetInfo; |
| using ::com::sun::star::lang::XMultiServiceFactory; |
| using ::com::sun::star::beans::Property; |
| using ::com::sun::star::sdb::application::XCopyTableWizard; |
| using ::com::sun::star::sdb::application::XCopyTableListener; |
| using ::com::sun::star::sdb::application::CopyTableRowEvent; |
| using ::com::sun::star::beans::Optional; |
| using ::com::sun::star::lang::IllegalArgumentException; |
| using ::com::sun::star::ucb::AlreadyInitializedException; |
| using ::com::sun::star::beans::XPropertySet; |
| using ::com::sun::star::lang::NotInitializedException; |
| using ::com::sun::star::lang::XServiceInfo; |
| using ::com::sun::star::sdbc::XConnection; |
| using ::com::sun::star::sdbc::XDataSource; |
| using ::com::sun::star::container::XNameAccess; |
| using ::com::sun::star::container::XChild; |
| using ::com::sun::star::task::XInteractionHandler; |
| using ::com::sun::star::frame::XModel; |
| using ::com::sun::star::sdb::XDocumentDataSource; |
| using ::com::sun::star::sdb::XCompletedConnection; |
| using ::com::sun::star::lang::WrappedTargetException; |
| using ::com::sun::star::sdbcx::XTablesSupplier; |
| using ::com::sun::star::sdb::XQueriesSupplier; |
| using ::com::sun::star::lang::DisposedException; |
| using ::com::sun::star::sdbc::XPreparedStatement; |
| using ::com::sun::star::sdb::XSingleSelectQueryComposer; |
| using ::com::sun::star::sdbc::XDatabaseMetaData; |
| using ::com::sun::star::sdbcx::XColumnsSupplier; |
| using ::com::sun::star::sdbc::XParameters; |
| using ::com::sun::star::sdbc::XResultSet; |
| using ::com::sun::star::sdbc::XRow; |
| using ::com::sun::star::sdbc::XBlob; |
| using ::com::sun::star::sdbc::XClob; |
| using ::com::sun::star::sdbcx::XRowLocate; |
| using ::com::sun::star::sdbc::XResultSetMetaDataSupplier; |
| using ::com::sun::star::sdbc::XResultSetMetaData; |
| using ::com::sun::star::sdbc::SQLException; |
| using ::com::sun::star::sdb::SQLContext; |
| using ::com::sun::star::sdbc::XDriverManager; |
| using ::com::sun::star::beans::PropertyValue; |
| /** === end UNO using === **/ |
| namespace CopyTableOperation = ::com::sun::star::sdb::application::CopyTableOperation; |
| namespace CopyTableContinuation = ::com::sun::star::sdb::application::CopyTableContinuation; |
| namespace CommandType = ::com::sun::star::sdb::CommandType; |
| namespace DataType = ::com::sun::star::sdbc::DataType; |
| |
| typedef ::utl::SharedUNOComponent< XConnection > SharedConnection; |
| typedef Reference< XInteractionHandler > InteractionHandler; |
| |
| //========================================================================= |
| //= CopyTableWizard |
| //========================================================================= |
| typedef ::svt::OGenericUnoDialog CopyTableWizard_DialogBase; |
| typedef ::cppu::ImplInheritanceHelper1 < CopyTableWizard_DialogBase |
| , XCopyTableWizard |
| > CopyTableWizard_Base; |
| class CopyTableWizard |
| :public CopyTableWizard_Base |
| ,public ::comphelper::OPropertyArrayUsageHelper< CopyTableWizard > |
| { |
| public: |
| // XServiceInfo |
| virtual ::rtl::OUString SAL_CALL getImplementationName() throw(RuntimeException); |
| virtual ::comphelper::StringSequence SAL_CALL getSupportedServiceNames() throw(RuntimeException); |
| |
| // XServiceInfo - static methods |
| static Sequence< ::rtl::OUString > getSupportedServiceNames_Static(void) throw( RuntimeException ); |
| static ::rtl::OUString getImplementationName_Static(void) throw( RuntimeException ); |
| static Reference< XInterface > Create( const Reference< XMultiServiceFactory >& ); |
| |
| // XCopyTableWizard |
| virtual ::sal_Int16 SAL_CALL getOperation() throw (RuntimeException); |
| virtual void SAL_CALL setOperation( ::sal_Int16 _operation ) throw (IllegalArgumentException, RuntimeException); |
| virtual ::rtl::OUString SAL_CALL getDestinationTableName() throw (RuntimeException); |
| virtual void SAL_CALL setDestinationTableName( const ::rtl::OUString& _destinationTableName ) throw (RuntimeException); |
| virtual Optional< ::rtl::OUString > SAL_CALL getCreatePrimaryKey() throw (RuntimeException); |
| virtual void SAL_CALL setCreatePrimaryKey( const Optional< ::rtl::OUString >& _newPrimaryKey ) throw (IllegalArgumentException, RuntimeException); |
| virtual sal_Bool SAL_CALL getUseHeaderLineAsColumnNames() throw (RuntimeException); |
| virtual void SAL_CALL setUseHeaderLineAsColumnNames( sal_Bool _bUseHeaderLineAsColumnNames ) throw (RuntimeException); |
| virtual void SAL_CALL addCopyTableListener( const Reference< XCopyTableListener >& Listener ) throw (RuntimeException); |
| virtual void SAL_CALL removeCopyTableListener( const Reference< XCopyTableListener >& Listener ) throw (RuntimeException); |
| |
| // XCopyTableWizard::XExecutableDialog |
| virtual void SAL_CALL setTitle( const ::rtl::OUString& aTitle ) throw (RuntimeException); |
| virtual ::sal_Int16 SAL_CALL execute( ) throw (RuntimeException); |
| |
| // XInitialization |
| virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException); |
| |
| // XPropertySet |
| virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo() throw(RuntimeException); |
| virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); |
| |
| // OPropertyArrayUsageHelper |
| virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; |
| |
| public: |
| ::osl::Mutex& getMutex() { return m_aMutex; } |
| bool isInitialized() const { return m_xSourceConnection.is() && m_pSourceObject.get() && m_xDestConnection.is(); } |
| |
| protected: |
| CopyTableWizard( const Reference< XMultiServiceFactory >& _rxORB ); |
| ~CopyTableWizard(); |
| |
| // OGenericUnoDialog overridables |
| virtual Dialog* createDialog( Window* _pParent ); |
| virtual void executedDialog( sal_Int16 _nExecutionResult ); |
| |
| private: |
| /// ensures our current attribute values are reflected in the dialog |
| void impl_attributesToDialog_nothrow( OCopyTableWizard& _rDialog ) const; |
| |
| /// ensures the current dialog settings are reflected in our attributes |
| void impl_dialogToAttributes_nothrow( const OCopyTableWizard& _rDialog ); |
| |
| /** returns our typed dialog |
| |
| @throws ::com::sun::star::uno::RuntimeException |
| if we don't have a dialog at the moment the method is called |
| */ |
| OCopyTableWizard& |
| impl_getDialog_throw(); |
| |
| /** returns our typed dialog |
| |
| @throws ::com::sun::star::uno::RuntimeException |
| if we don't have a dialog at the moment the method is called |
| */ |
| const OCopyTableWizard& |
| impl_getDialog_throw() const; |
| |
| /** ensures the given argument sequence contains a valid data access descriptor at the given position |
| @param _rAllArgs |
| the arguments as passed to ->initialize |
| @param _nArgPos |
| the position within ->_rAllArgs which contains the data access descriptor |
| @param _out_rxConnection |
| will, upon successful return, contain the connection for the data source |
| @param _out_rxDocInteractionHandler |
| will, upon successful return, contain the interaction handler which could |
| be deduced from database document described by the descriptor, if any. |
| (It is possible that the descriptor does not allow to deduce a database document, |
| in which case <code>_out_rxDocInteractionHandler</code> will be <NULL/>.) |
| @return the data access descriptor |
| */ |
| Reference< XPropertySet > |
| impl_ensureDataAccessDescriptor_throw( |
| const Sequence< Any >& _rAllArgs, |
| const sal_Int16 _nArgPos, |
| SharedConnection& _out_rxConnection, |
| InteractionHandler& _out_rxDocInteractionHandler |
| ) const; |
| |
| /** extracts the source object (table or query) described by the given descriptor, |
| relative to m_xSourceConnection |
| */ |
| ::std::auto_ptr< ICopyTableSourceObject > |
| impl_extractSourceObject_throw( |
| const Reference< XPropertySet >& _rxDescriptor, |
| sal_Int32& _out_rCommandType |
| ) const; |
| |
| /** extracts the result set to copy records from, and the selection-related aspects, if any. |
| |
| Effectively, this method extracts m_xSourceResultSet, m_aSourceSelection, and m_bSourceSelectionBookmarks. |
| |
| If an inconsistent/insufficent sub set of those properties is present in the descriptor, and exception |
| is thrown. |
| */ |
| void impl_extractSourceResultSet_throw( |
| const Reference< XPropertySet >& i_rDescriptor |
| ); |
| |
| /** checks whether the given copy source descriptor contains settings which are not |
| supported (yet) |
| |
| Throws an IllegalArgumentException if the descriptor contains a valid setting, which is |
| not yet supported. |
| */ |
| void impl_checkForUnsupportedSettings_throw( |
| const Reference< XPropertySet >& _rxSourceDescriptor ) const; |
| |
| /** obtaines the connection described by the given data access descriptor |
| |
| If needed and possible, the method will ask the user, using the interaction |
| handler associated with the database described by the descriptor. |
| |
| All errors are handled with the InteractionHandler associated with the data source, |
| if there is one. Else, they will be silenced (but asserted in non-product builds). |
| |
| @param _rxDataSourceDescriptor |
| the data access descriptor describing the data source whose connection |
| should be obtained. Must not be <NULL/>. |
| @param _out_rxDocInteractionHandler |
| the interaction handler which could be deduced from the descriptor |
| |
| @throws RuntimeException |
| if anything goes seriously wrong. |
| */ |
| SharedConnection |
| impl_extractConnection_throw( |
| const Reference< XPropertySet >& _rxDataSourceDescriptor, |
| InteractionHandler& _out_rxDocInteractionHandler |
| ) const; |
| |
| /** actually copies the table |
| |
| This method is called after the dialog has been successfully executed. |
| */ |
| void impl_doCopy_nothrow(); |
| |
| /** creates the INSERT INTO statement |
| @param _xTable The destination table. |
| */ |
| ::rtl::OUString impl_getServerSideCopyStatement_throw( const Reference< XPropertySet >& _xTable ); |
| |
| /** creates the statement which, when executed, will produce the source data to copy |
| |
| If the source object refers to a query which contains parameters, those parameters |
| are filled in, using an interaction handler. |
| */ |
| ::utl::SharedUNOComponent< XPreparedStatement > |
| impl_createSourceStatement_throw() const; |
| |
| /** copies the data rows from the given source result set to the given destination table |
| */ |
| void impl_copyRows_throw( |
| const Reference< XResultSet >& _rxSourceResultSet, |
| const Reference< XPropertySet >& _rxDestTable |
| ); |
| |
| /** processes an error which occured during copying |
| |
| First, all listeners are ask. If a listener tells to cancel or continue copying, this is reported to the |
| method's caller. If a listener tells to ask the user, this is done, and the user's decision is |
| reported to the method's caller. |
| |
| @return |
| <TRUE/> if and only if copying should be continued. |
| */ |
| bool impl_processCopyError_nothrow( |
| const CopyTableRowEvent& _rEvent ); |
| |
| private: |
| ::comphelper::ComponentContext m_aContext; |
| |
| // attributes |
| sal_Int16 m_nOperation; |
| ::rtl::OUString m_sDestinationTable; |
| Optional< ::rtl::OUString > m_aPrimaryKeyName; |
| sal_Bool m_bUseHeaderLineAsColumnNames; |
| |
| // source |
| SharedConnection m_xSourceConnection; |
| sal_Int32 m_nCommandType; |
| ::std::auto_ptr< ICopyTableSourceObject > |
| m_pSourceObject; |
| Reference< XResultSet > m_xSourceResultSet; |
| Sequence< Any > m_aSourceSelection; |
| sal_Bool m_bSourceSelectionBookmarks; |
| |
| // destination |
| SharedConnection m_xDestConnection; |
| |
| // other |
| InteractionHandler m_xInteractionHandler; |
| ::cppu::OInterfaceContainerHelper |
| m_aCopyTableListeners; |
| sal_Int16 m_nOverrideExecutionResult; |
| }; |
| |
| //========================================================================= |
| //= MethodGuard |
| //========================================================================= |
| class CopyTableAccessGuard |
| { |
| public: |
| CopyTableAccessGuard( CopyTableWizard& _rWizard ) |
| :m_rWizard( _rWizard ) |
| { |
| m_rWizard.getMutex().acquire(); |
| if ( !m_rWizard.isInitialized() ) |
| throw NotInitializedException(); |
| } |
| |
| ~CopyTableAccessGuard() |
| { |
| m_rWizard.getMutex().release(); |
| } |
| |
| private: |
| CopyTableWizard& m_rWizard; |
| }; |
| |
| //========================================================================= |
| //------------------------------------------------------------------------- |
| CopyTableWizard::CopyTableWizard( const Reference< XMultiServiceFactory >& _rxORB ) |
| :CopyTableWizard_Base( _rxORB ) |
| ,m_aContext( _rxORB ) |
| ,m_nOperation( CopyTableOperation::CopyDefinitionAndData ) |
| ,m_sDestinationTable() |
| ,m_aPrimaryKeyName( sal_False, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ID" ) )) |
| ,m_bUseHeaderLineAsColumnNames( sal_True ) |
| ,m_xSourceConnection() |
| ,m_nCommandType( CommandType::COMMAND ) |
| ,m_pSourceObject() |
| ,m_xSourceResultSet() |
| ,m_aSourceSelection() |
| ,m_bSourceSelectionBookmarks( sal_True ) |
| ,m_xDestConnection() |
| ,m_aCopyTableListeners( m_aMutex ) |
| ,m_nOverrideExecutionResult( -1 ) |
| { |
| } |
| |
| //------------------------------------------------------------------------- |
| CopyTableWizard::~CopyTableWizard() |
| { |
| acquire(); |
| |
| // protect some members whose dtor might potentially throw |
| try { m_xSourceConnection.clear(); } |
| catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } |
| try { m_xDestConnection.clear(); } |
| catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } |
| |
| // TODO: shouldn't we have explicit disposal support? If a listener is registered |
| // at our instance, and perhaps holds this our instance by a hard ref, then we'll never |
| // be destroyed. |
| // However, adding XComponent support to the GenericUNODialog probably requires |
| // some thinking - would it break existing clients which do not call a dispose, then? |
| } |
| |
| //------------------------------------------------------------------------- |
| Reference< XInterface > CopyTableWizard::Create( const Reference< XMultiServiceFactory >& _rxFactory ) |
| { |
| return *( new CopyTableWizard( _rxFactory ) ); |
| } |
| |
| //------------------------------------------------------------------------- |
| ::rtl::OUString SAL_CALL CopyTableWizard::getImplementationName() throw(RuntimeException) |
| { |
| return getImplementationName_Static(); |
| } |
| |
| //------------------------------------------------------------------------- |
| ::rtl::OUString CopyTableWizard::getImplementationName_Static() throw(RuntimeException) |
| { |
| return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.dbu.CopyTableWizard" ) ); |
| } |
| |
| //------------------------------------------------------------------------- |
| ::comphelper::StringSequence SAL_CALL CopyTableWizard::getSupportedServiceNames() throw(RuntimeException) |
| { |
| return getSupportedServiceNames_Static(); |
| } |
| |
| //------------------------------------------------------------------------- |
| ::comphelper::StringSequence CopyTableWizard::getSupportedServiceNames_Static() throw(RuntimeException) |
| { |
| ::comphelper::StringSequence aSupported(1); |
| aSupported.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.application.CopyTableWizard" ) ); |
| return aSupported; |
| } |
| |
| //------------------------------------------------------------------------- |
| Reference< XPropertySetInfo > SAL_CALL CopyTableWizard::getPropertySetInfo() throw(RuntimeException) |
| { |
| Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); |
| return xInfo; |
| } |
| |
| //-------------------------------------------------------------------- |
| ::sal_Int16 SAL_CALL CopyTableWizard::getOperation() throw (RuntimeException) |
| { |
| CopyTableAccessGuard aGuard( *this ); |
| return m_nOperation; |
| } |
| |
| //-------------------------------------------------------------------- |
| void SAL_CALL CopyTableWizard::setOperation( ::sal_Int16 _operation ) throw (IllegalArgumentException, RuntimeException) |
| { |
| CopyTableAccessGuard aGuard( *this ); |
| |
| if ( ( _operation != CopyTableOperation::CopyDefinitionAndData ) |
| && ( _operation != CopyTableOperation::CopyDefinitionOnly ) |
| && ( _operation != CopyTableOperation::CreateAsView ) |
| && ( _operation != CopyTableOperation::AppendData ) |
| ) |
| throw IllegalArgumentException( ::rtl::OUString(), *this, 1 ); |
| |
| if ( ( _operation == CopyTableOperation::CreateAsView ) |
| && !OCopyTableWizard::supportsViews( m_xDestConnection ) |
| ) |
| throw IllegalArgumentException( |
| String( ModuleRes( STR_CTW_NO_VIEWS_SUPPORT ) ), |
| *this, |
| 1 |
| ); |
| |
| m_nOperation = _operation; |
| } |
| |
| //-------------------------------------------------------------------- |
| ::rtl::OUString SAL_CALL CopyTableWizard::getDestinationTableName() throw (RuntimeException) |
| { |
| CopyTableAccessGuard aGuard( *this ); |
| return m_sDestinationTable; |
| } |
| |
| //-------------------------------------------------------------------- |
| void SAL_CALL CopyTableWizard::setDestinationTableName( const ::rtl::OUString& _destinationTableName ) throw (RuntimeException) |
| { |
| CopyTableAccessGuard aGuard( *this ); |
| m_sDestinationTable = _destinationTableName; |
| } |
| |
| //-------------------------------------------------------------------- |
| Optional< ::rtl::OUString > SAL_CALL CopyTableWizard::getCreatePrimaryKey() throw (RuntimeException) |
| { |
| CopyTableAccessGuard aGuard( *this ); |
| return m_aPrimaryKeyName; |
| } |
| |
| //-------------------------------------------------------------------- |
| void SAL_CALL CopyTableWizard::setCreatePrimaryKey( const Optional< ::rtl::OUString >& _newPrimaryKey ) throw (IllegalArgumentException, RuntimeException) |
| { |
| CopyTableAccessGuard aGuard( *this ); |
| |
| if ( _newPrimaryKey.IsPresent && !OCopyTableWizard::supportsPrimaryKey( m_xDestConnection ) ) |
| throw IllegalArgumentException( |
| String( ModuleRes( STR_CTW_NO_PRIMARY_KEY_SUPPORT ) ), |
| *this, |
| 1 |
| ); |
| |
| m_aPrimaryKeyName = _newPrimaryKey; |
| } |
| // ----------------------------------------------------------------------------- |
| sal_Bool SAL_CALL CopyTableWizard::getUseHeaderLineAsColumnNames() throw (RuntimeException) |
| { |
| CopyTableAccessGuard aGuard( *this ); |
| return m_bUseHeaderLineAsColumnNames; |
| } |
| // ----------------------------------------------------------------------------- |
| void SAL_CALL CopyTableWizard::setUseHeaderLineAsColumnNames( sal_Bool _bUseHeaderLineAsColumnNames ) throw (RuntimeException) |
| { |
| CopyTableAccessGuard aGuard( *this ); |
| m_bUseHeaderLineAsColumnNames = _bUseHeaderLineAsColumnNames; |
| } |
| //-------------------------------------------------------------------- |
| void SAL_CALL CopyTableWizard::addCopyTableListener( const Reference< XCopyTableListener >& _rxListener ) throw (RuntimeException) |
| { |
| CopyTableAccessGuard aGuard( *this ); |
| if ( _rxListener.is() ) |
| m_aCopyTableListeners.addInterface( _rxListener ); |
| } |
| |
| //-------------------------------------------------------------------- |
| void SAL_CALL CopyTableWizard::removeCopyTableListener( const Reference< XCopyTableListener >& _rxListener ) throw (RuntimeException) |
| { |
| CopyTableAccessGuard aGuard( *this ); |
| if ( _rxListener.is() ) |
| m_aCopyTableListeners.removeInterface( _rxListener ); |
| } |
| |
| //-------------------------------------------------------------------- |
| void SAL_CALL CopyTableWizard::setTitle( const ::rtl::OUString& _rTitle ) throw (RuntimeException) |
| { |
| CopyTableAccessGuard aGuard( *this ); |
| CopyTableWizard_DialogBase::setTitle( _rTitle ); |
| } |
| |
| //-------------------------------------------------------------------- |
| ::sal_Int16 SAL_CALL CopyTableWizard::execute( ) throw (RuntimeException) |
| { |
| CopyTableAccessGuard aGuard( *this ); |
| |
| m_nOverrideExecutionResult = -1; |
| sal_Int16 nExecutionResult = CopyTableWizard_DialogBase::execute(); |
| if ( m_nOverrideExecutionResult ) |
| nExecutionResult = m_nOverrideExecutionResult; |
| |
| return nExecutionResult; |
| } |
| |
| //------------------------------------------------------------------------- |
| OCopyTableWizard& CopyTableWizard::impl_getDialog_throw() |
| { |
| OCopyTableWizard* pWizard = dynamic_cast< OCopyTableWizard* >( m_pDialog ); |
| if ( !pWizard ) |
| throw DisposedException( ::rtl::OUString(), *this ); |
| return *pWizard; |
| } |
| |
| //------------------------------------------------------------------------- |
| const OCopyTableWizard& CopyTableWizard::impl_getDialog_throw() const |
| { |
| const OCopyTableWizard* pWizard = dynamic_cast< const OCopyTableWizard* >( m_pDialog ); |
| if ( !pWizard ) |
| throw DisposedException( ::rtl::OUString(), *const_cast< CopyTableWizard* >( this ) ); |
| return *pWizard; |
| } |
| |
| //------------------------------------------------------------------------- |
| void CopyTableWizard::impl_attributesToDialog_nothrow( OCopyTableWizard& _rDialog ) const |
| { |
| // primary key column |
| _rDialog.setCreatePrimaryKey( m_aPrimaryKeyName.IsPresent, m_aPrimaryKeyName.Value ); |
| _rDialog.setUseHeaderLine(m_bUseHeaderLineAsColumnNames); |
| |
| // everything else was passed at construction time already |
| } |
| |
| //------------------------------------------------------------------------- |
| void CopyTableWizard::impl_dialogToAttributes_nothrow( const OCopyTableWizard& _rDialog ) |
| { |
| m_aPrimaryKeyName.IsPresent = _rDialog.shouldCreatePrimaryKey(); |
| if ( m_aPrimaryKeyName.IsPresent ) |
| m_aPrimaryKeyName.Value = _rDialog.getPrimaryKeyName(); |
| else |
| m_aPrimaryKeyName.Value = ::rtl::OUString(); |
| |
| m_sDestinationTable = _rDialog.getName(); |
| |
| m_nOperation = _rDialog.getOperation(); |
| m_bUseHeaderLineAsColumnNames = _rDialog.UseHeaderLine(); |
| } |
| |
| //------------------------------------------------------------------------- |
| namespace |
| { |
| //..................................................................... |
| /** tries to obtain the InteractionHandler associated with a given data source |
| |
| If the data source is a sdb-level data source, it will have a DatabaseDocument associated |
| with it. This doocument may have an InteractionHandler used while loading it. |
| |
| @throws RuntimeException |
| if it occures during invoking any of the data source's methods, or if any of the involved |
| components violates its contract by not providing the required interfaces |
| */ |
| InteractionHandler lcl_getInteractionHandler_throw( const Reference< XDataSource >& _rxDataSource, const InteractionHandler& _rFallback ) |
| { |
| InteractionHandler xHandler( _rFallback ); |
| |
| // try to obtain the document model |
| Reference< XModel > xDocumentModel; |
| Reference< XDocumentDataSource > xDocDataSource( _rxDataSource, UNO_QUERY ); |
| if ( xDocDataSource.is() ) |
| xDocumentModel.set( xDocDataSource->getDatabaseDocument(), UNO_QUERY_THROW ); |
| |
| // see whether the document model can provide a handler |
| if ( xDocumentModel.is() ) |
| { |
| ::comphelper::NamedValueCollection aModelArgs( xDocumentModel->getArgs() ); |
| xHandler = aModelArgs.getOrDefault( "InteractionHandler", xHandler ); |
| } |
| |
| return xHandler; |
| } |
| //..................................................................... |
| /** tries to obtain the InteractionHandler associated with a given connection |
| |
| If the connection belongs to a sdb-level data source, then this data source |
| is examined for an interaction handler. Else, <NULL/> is returned. |
| |
| @throws RuntimeException |
| if it occures during invoking any of the data source's methods, or if any of the involved |
| components violates its contract by not providing the required interfaces |
| */ |
| InteractionHandler lcl_getInteractionHandler_throw( const Reference< XConnection >& _rxConnection, const InteractionHandler& _rFallback ) |
| { |
| // try whether there is a data source which the connection belongs to |
| Reference< XDataSource > xDataSource; |
| Reference< XChild > xAsChild( _rxConnection, UNO_QUERY ); |
| if ( xAsChild.is() ) |
| xDataSource = xDataSource.query( xAsChild->getParent() ); |
| |
| if ( xDataSource.is() ) |
| return lcl_getInteractionHandler_throw( xDataSource, _rFallback ); |
| |
| return _rFallback; |
| } |
| } |
| |
| //------------------------------------------------------------------------- |
| Reference< XPropertySet > CopyTableWizard::impl_ensureDataAccessDescriptor_throw( |
| const Sequence< Any >& _rAllArgs, const sal_Int16 _nArgPos, SharedConnection& _out_rxConnection, |
| InteractionHandler& _out_rxDocInteractionHandler ) const |
| { |
| Reference< XPropertySet > xDescriptor; |
| _rAllArgs[ _nArgPos ] >>= xDescriptor; |
| |
| // the descriptor must be non-NULL, of course |
| bool bIsValid = xDescriptor.is(); |
| |
| // it must support the proper service |
| if ( bIsValid ) |
| { |
| Reference< XServiceInfo > xSI( xDescriptor, UNO_QUERY ); |
| bIsValid = ( xSI.is() |
| && xSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.DataAccessDescriptor" ) ) ) |
| ); |
| } |
| |
| // it must be able to provide a connection |
| if ( bIsValid ) |
| { |
| _out_rxConnection = impl_extractConnection_throw( xDescriptor, _out_rxDocInteractionHandler ); |
| bIsValid = _out_rxConnection.is(); |
| } |
| |
| if ( !bIsValid ) |
| { |
| throw IllegalArgumentException( |
| String( ModuleRes( STR_CTW_INVALID_DATA_ACCESS_DESCRIPTOR ) ), |
| *const_cast< CopyTableWizard* >( this ), |
| _nArgPos + 1 |
| ); |
| } |
| |
| return xDescriptor; |
| } |
| |
| //------------------------------------------------------------------------- |
| namespace |
| { |
| bool lcl_hasNonEmptyStringValue_throw( const Reference< XPropertySet >& _rxDescriptor, |
| const Reference< XPropertySetInfo > _rxPSI, const ::rtl::OUString& _rPropertyName ) |
| { |
| ::rtl::OUString sValue; |
| if ( _rxPSI->hasPropertyByName( _rPropertyName ) ) |
| { |
| OSL_VERIFY( _rxDescriptor->getPropertyValue( _rPropertyName ) >>= sValue ); |
| } |
| return sValue.getLength() > 0; |
| } |
| } |
| |
| //------------------------------------------------------------------------- |
| void CopyTableWizard::impl_checkForUnsupportedSettings_throw( const Reference< XPropertySet >& _rxSourceDescriptor ) const |
| { |
| OSL_PRECOND( _rxSourceDescriptor.is(), "CopyTableWizard::impl_checkForUnsupportedSettings_throw: illegal argument!" ); |
| Reference< XPropertySetInfo > xPSI( _rxSourceDescriptor->getPropertySetInfo(), UNO_SET_THROW ); |
| ::rtl::OUString sUnsupportedSetting; |
| |
| const ::rtl::OUString aSettings[] = { |
| PROPERTY_FILTER, PROPERTY_ORDER, PROPERTY_HAVING_CLAUSE, PROPERTY_GROUP_BY |
| }; |
| for ( size_t i=0; i < sizeof( aSettings ) / sizeof( aSettings[0] ); ++i ) |
| { |
| if ( lcl_hasNonEmptyStringValue_throw( _rxSourceDescriptor, xPSI, aSettings[i] ) ) |
| { |
| sUnsupportedSetting = aSettings[i]; |
| break; |
| } |
| } |
| |
| if ( sUnsupportedSetting.getLength() != 0 ) |
| { |
| ::rtl::OUString sMessage( String(ModuleRes( STR_CTW_ERROR_UNSUPPORTED_SETTING )) ); |
| ::comphelper::string::searchAndReplaceAsciiI( sMessage, "$name$", sUnsupportedSetting ); |
| throw IllegalArgumentException( |
| sMessage, |
| *const_cast< CopyTableWizard* >( this ), |
| 1 |
| ); |
| } |
| |
| } |
| |
| //------------------------------------------------------------------------- |
| ::std::auto_ptr< ICopyTableSourceObject > CopyTableWizard::impl_extractSourceObject_throw( const Reference< XPropertySet >& _rxDescriptor, sal_Int32& _out_rCommandType ) const |
| { |
| OSL_PRECOND( _rxDescriptor.is() && m_xSourceConnection.is(), "CopyTableWizard::impl_extractSourceObject_throw: illegal arguments!" ); |
| |
| Reference< XPropertySetInfo > xPSI( _rxDescriptor->getPropertySetInfo(), UNO_SET_THROW ); |
| if ( !xPSI->hasPropertyByName( PROPERTY_COMMAND ) |
| || !xPSI->hasPropertyByName( PROPERTY_COMMAND_TYPE ) |
| ) |
| throw IllegalArgumentException( |
| ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Expecting a table or query specification." ) ), |
| // TODO: resource |
| *const_cast< CopyTableWizard* >( this ), |
| 1 |
| ); |
| |
| ::rtl::OUString sCommand; |
| _out_rCommandType = CommandType::COMMAND; |
| OSL_VERIFY( _rxDescriptor->getPropertyValue( PROPERTY_COMMAND ) >>= sCommand ); |
| OSL_VERIFY( _rxDescriptor->getPropertyValue( PROPERTY_COMMAND_TYPE ) >>= _out_rCommandType ); |
| |
| ::std::auto_ptr< ICopyTableSourceObject > pSourceObject; |
| Reference< XNameAccess > xContainer; |
| switch ( _out_rCommandType ) |
| { |
| case CommandType::TABLE: |
| { |
| Reference< XTablesSupplier > xSuppTables( m_xSourceConnection.getTyped(), UNO_QUERY ); |
| if ( xSuppTables.is() ) |
| xContainer.set( xSuppTables->getTables(), UNO_SET_THROW ); |
| } |
| break; |
| case CommandType::QUERY: |
| { |
| Reference< XQueriesSupplier > xSuppQueries( m_xSourceConnection.getTyped(), UNO_QUERY ); |
| if ( xSuppQueries.is() ) |
| xContainer.set( xSuppQueries->getQueries(), UNO_SET_THROW ); |
| } |
| break; |
| default: |
| throw IllegalArgumentException( |
| String( ModuleRes( STR_CTW_ONLY_TABLES_AND_QUERIES_SUPPORT ) ), |
| *const_cast< CopyTableWizard* >( this ), |
| 1 |
| ); |
| } |
| |
| if ( xContainer.is() ) |
| { |
| pSourceObject.reset( new ObjectCopySource( m_xSourceConnection, |
| Reference< XPropertySet >( xContainer->getByName( sCommand ), UNO_QUERY_THROW ) ) ); |
| } |
| else |
| { |
| // our source connection is an SDBC level connection only, not a SDBCX level one |
| // Which means it cannot provide the to-be-copied object as component. |
| |
| if ( _out_rCommandType == CommandType::QUERY ) |
| // we cannot copy a query if the connection cannot provide it ... |
| throw IllegalArgumentException( |
| String(ModuleRes( STR_CTW_ERROR_NO_QUERY )), |
| *const_cast< CopyTableWizard* >( this ), |
| 1 |
| ); |
| pSourceObject.reset( new NamedTableCopySource( m_xSourceConnection, sCommand ) ); |
| } |
| |
| return pSourceObject; |
| } |
| |
| //------------------------------------------------------------------------- |
| void CopyTableWizard::impl_extractSourceResultSet_throw( const Reference< XPropertySet >& i_rDescriptor ) |
| { |
| Reference< XPropertySetInfo > xPSI( i_rDescriptor->getPropertySetInfo(), UNO_SET_THROW ); |
| |
| // extract relevant settings |
| if ( xPSI->hasPropertyByName( PROPERTY_RESULT_SET ) ) |
| m_xSourceResultSet.set( i_rDescriptor->getPropertyValue( PROPERTY_RESULT_SET ), UNO_QUERY ); |
| |
| if ( xPSI->hasPropertyByName( PROPERTY_SELECTION ) ) |
| OSL_VERIFY( i_rDescriptor->getPropertyValue( PROPERTY_SELECTION ) >>= m_aSourceSelection ); |
| |
| if ( xPSI->hasPropertyByName( PROPERTY_BOOKMARK_SELECTION ) ) |
| OSL_VERIFY( i_rDescriptor->getPropertyValue( PROPERTY_BOOKMARK_SELECTION ) >>= m_bSourceSelectionBookmarks ); |
| |
| // sanity checks |
| const bool bHasResultSet = m_xSourceResultSet.is(); |
| const bool bHasSelection = ( m_aSourceSelection.getLength() != 0 ); |
| if ( bHasSelection && !bHasResultSet ) |
| throw IllegalArgumentException( |
| ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "A result set is needed when specifying a selection to copy." ) ), |
| // TODO: resource |
| *this, |
| 1 |
| ); |
| |
| if ( bHasSelection && m_bSourceSelectionBookmarks ) |
| { |
| Reference< XRowLocate > xRowLocate( m_xSourceResultSet, UNO_QUERY ); |
| if ( !xRowLocate.is() ) |
| { |
| ::dbtools::throwGenericSQLException( |
| String( ModuleRes( STR_CTW_COPY_SOURCE_NEEDS_BOOKMARKS ) ), |
| *this |
| ); |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------- |
| SharedConnection CopyTableWizard::impl_extractConnection_throw( const Reference< XPropertySet >& _rxDataSourceDescriptor, |
| InteractionHandler& _out_rxDocInteractionHandler ) const |
| { |
| SharedConnection xConnection; |
| |
| OSL_PRECOND( _rxDataSourceDescriptor.is(), "CopyTableWizard::impl_extractConnection_throw: no descriptor!" ); |
| if ( !_rxDataSourceDescriptor.is() ) |
| return xConnection; |
| |
| InteractionHandler xInteractionHandler; |
| |
| do |
| { |
| Reference< XPropertySetInfo > xPSI( _rxDataSourceDescriptor->getPropertySetInfo(), UNO_SET_THROW ); |
| |
| // if there's an ActiveConnection, use it |
| if ( xPSI->hasPropertyByName( PROPERTY_ACTIVE_CONNECTION ) ) |
| { |
| Reference< XConnection > xPure; |
| OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xPure ); |
| xConnection.reset( xPure, SharedConnection::NoTakeOwnership ); |
| } |
| if ( xConnection.is() ) |
| { |
| xInteractionHandler = lcl_getInteractionHandler_throw( xConnection.getTyped(), m_xInteractionHandler ); |
| OSL_POSTCOND( xInteractionHandler.is(), "CopyTableWizard::impl_extractConnection_throw: lcl_getInteractionHandler_throw returned nonsense!" ); |
| break; |
| } |
| |
| // there could be a DataSourceName or a DatabaseLocation, describing the css.sdb.DataSource |
| ::rtl::OUString sDataSource, sDatabaseLocation; |
| if ( xPSI->hasPropertyByName( PROPERTY_DATASOURCENAME ) ) |
| OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_DATASOURCENAME ) >>= sDataSource ); |
| if ( xPSI->hasPropertyByName( PROPERTY_DATABASE_LOCATION ) ) |
| OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_DATABASE_LOCATION ) >>= sDatabaseLocation ); |
| |
| // need a DatabaseContext for loading the data source |
| Reference< XNameAccess > xDatabaseContext( m_aContext.createComponent( "com.sun.star.sdb.DatabaseContext" ), UNO_QUERY_THROW ); |
| Reference< XDataSource > xDataSource; |
| if ( sDataSource.getLength() ) |
| xDataSource.set( xDatabaseContext->getByName( sDataSource ), UNO_QUERY_THROW ); |
| if ( !xDataSource.is() && sDatabaseLocation.getLength() ) |
| xDataSource.set( xDatabaseContext->getByName( sDatabaseLocation ), UNO_QUERY_THROW ); |
| |
| if ( xDataSource.is() ) |
| { |
| // first, try connecting with completion |
| xInteractionHandler = lcl_getInteractionHandler_throw( xDataSource, m_xInteractionHandler ); |
| OSL_POSTCOND( xInteractionHandler.is(), "CopyTableWizard::impl_extractConnection_throw: lcl_getInteractionHandler_throw returned nonsense!" ); |
| if ( xInteractionHandler.is() ) |
| { |
| Reference< XCompletedConnection > xInteractiveConnection( xDataSource, UNO_QUERY ); |
| if ( xInteractiveConnection.is() ) |
| xConnection.reset( xInteractiveConnection->connectWithCompletion( xInteractionHandler ), SharedConnection::TakeOwnership ); |
| } |
| |
| // interactively connecting was not successful or possible -> connect without interaction |
| if ( !xConnection.is() ) |
| { |
| xConnection.reset( xDataSource->getConnection( ::rtl::OUString(), ::rtl::OUString() ), SharedConnection::TakeOwnership ); |
| } |
| } |
| |
| if ( xConnection.is() ) |
| break; |
| |
| // finally, there could be a ConnectionResource/ConnectionInfo |
| ::rtl::OUString sConnectionResource; |
| Sequence< PropertyValue > aConnectionInfo; |
| if ( xPSI->hasPropertyByName( PROPERTY_CONNECTION_RESOURCE ) ) |
| OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_CONNECTION_RESOURCE ) >>= sConnectionResource ); |
| if ( xPSI->hasPropertyByName( PROPERTY_CONNECTION_INFO ) ) |
| OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_CONNECTION_INFO ) >>= aConnectionInfo ); |
| |
| Reference< XDriverManager > xDriverManager; |
| xDriverManager.set( m_aContext.createComponent( "com.sun.star.sdbc.ConnectionPool" ), UNO_QUERY ); |
| if ( !xDriverManager.is() ) |
| // no connection pool installed |
| xDriverManager.set( m_aContext.createComponent( "com.sun.star.sdbc.DriverManager" ), UNO_QUERY_THROW ); |
| |
| if ( aConnectionInfo.getLength() ) |
| xConnection.set( xDriverManager->getConnectionWithInfo( sConnectionResource, aConnectionInfo ), UNO_SET_THROW ); |
| else |
| xConnection.set( xDriverManager->getConnection( sConnectionResource ), UNO_SET_THROW ); |
| } |
| while ( false ); |
| |
| if ( xInteractionHandler != m_xInteractionHandler ) |
| _out_rxDocInteractionHandler = xInteractionHandler; |
| |
| return xConnection; |
| } |
| |
| //------------------------------------------------------------------------- |
| ::utl::SharedUNOComponent< XPreparedStatement > CopyTableWizard::impl_createSourceStatement_throw() const |
| { |
| OSL_PRECOND( m_xSourceConnection.is(), "CopyTableWizard::impl_createSourceStatement_throw: illegal call!" ); |
| if ( !m_xSourceConnection.is() ) |
| throw RuntimeException( ::rtl::OUString(), *const_cast< CopyTableWizard* >( this ) ); |
| |
| ::utl::SharedUNOComponent< XPreparedStatement > xStatement; |
| switch ( m_nCommandType ) |
| { |
| case CommandType::TABLE: |
| xStatement.set( m_pSourceObject->getPreparedSelectStatement(), UNO_SET_THROW ); |
| break; |
| |
| case CommandType::QUERY: |
| { |
| ::rtl::OUString sQueryCommand( m_pSourceObject->getSelectStatement() ); |
| xStatement.set( m_pSourceObject->getPreparedSelectStatement(), UNO_SET_THROW ); |
| |
| // check whether we have to fill in parameter values |
| // create and fill a composer |
| |
| Reference< XMultiServiceFactory > xFactory( m_xSourceConnection, UNO_QUERY ); |
| ::utl::SharedUNOComponent< XSingleSelectQueryComposer > xComposer; |
| if ( xFactory.is() ) |
| // note: connections below the sdb-level are allowed to not support the XMultiServiceFactory interface |
| xComposer.set( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY ); |
| |
| if ( xComposer.is() ) |
| { |
| xComposer->setQuery( sQueryCommand ); |
| |
| Reference< XParameters > xStatementParams( xStatement, UNO_QUERY ); |
| OSL_ENSURE( xStatementParams.is(), "CopyTableWizard::impl_createSourceStatement_throw: no access to the statement's parameters!" ); |
| // the statement should be a css.sdbc.PreparedStatement (this is what |
| // we created), and a prepared statement is required to support XParameters |
| if ( xStatementParams.is() ) |
| { |
| OSL_ENSURE( m_xInteractionHandler.is(), |
| "CopyTableWizard::impl_createSourceStatement_throw: no interaction handler for the parameters request!" ); |
| // we should always have an interaction handler - as last fallback, we create an own one in ::initialize |
| |
| if ( m_xInteractionHandler.is() ) |
| ::dbtools::askForParameters( xComposer, xStatementParams, m_xSourceConnection, m_xInteractionHandler ); |
| } |
| } |
| } |
| break; |
| |
| default: |
| // this should not have survived initialization phase |
| throw RuntimeException( ::rtl::OUString(), *const_cast< CopyTableWizard* >( this ) ); |
| } |
| |
| return xStatement; |
| } |
| |
| //------------------------------------------------------------------------- |
| namespace |
| { |
| class ValueTransfer |
| { |
| public: |
| ValueTransfer( const sal_Int32& _rSourcePos, const sal_Int32& _rDestPos, const ::std::vector< sal_Int32 >& _rColTypes, |
| const Reference< XRow >& _rxSource, const Reference< XParameters >& _rxDest ) |
| :m_rSourcePos( _rSourcePos ) |
| ,m_rDestPos( _rDestPos ) |
| ,m_rColTypes( _rColTypes ) |
| ,m_xSource( _rxSource ) |
| ,m_xDest( _rxDest ) |
| { |
| } |
| |
| template< typename VALUE_TYPE > |
| void transferValue( VALUE_TYPE ( SAL_CALL XRow::*_pGetter )( sal_Int32 ), |
| void (SAL_CALL XParameters::*_pSetter)( sal_Int32, VALUE_TYPE ) ) |
| { |
| VALUE_TYPE value( (m_xSource.get()->*_pGetter)( m_rSourcePos ) ); |
| if ( m_xSource->wasNull() ) |
| m_xDest->setNull( m_rDestPos, m_rColTypes[ m_rSourcePos ] ); |
| else |
| (m_xDest.get()->*_pSetter)( m_rDestPos, value ); |
| } |
| template< typename VALUE_TYPE > |
| void transferComplexValue( VALUE_TYPE ( SAL_CALL XRow::*_pGetter )( sal_Int32 ), |
| void (SAL_CALL XParameters::*_pSetter)( sal_Int32, const VALUE_TYPE& ) ) |
| { |
| const VALUE_TYPE value( (m_xSource.get()->*_pGetter)( m_rSourcePos ) ); |
| { |
| if ( m_xSource->wasNull() ) |
| m_xDest->setNull( m_rDestPos, m_rColTypes[ m_rSourcePos ] ); |
| else |
| (m_xDest.get()->*_pSetter)( m_rDestPos, value ); |
| } |
| } |
| private: |
| const sal_Int32& m_rSourcePos; |
| const sal_Int32& m_rDestPos; |
| const ::std::vector< sal_Int32 > m_rColTypes; |
| const Reference< XRow > m_xSource; |
| const Reference< XParameters > m_xDest; |
| }; |
| } |
| |
| //------------------------------------------------------------------------- |
| bool CopyTableWizard::impl_processCopyError_nothrow( const CopyTableRowEvent& _rEvent ) |
| { |
| Reference< XCopyTableListener > xListener; |
| try |
| { |
| ::cppu::OInterfaceIteratorHelper aIter( m_aCopyTableListeners ); |
| while ( aIter.hasMoreElements() ) |
| { |
| xListener.set( aIter.next(), UNO_QUERY_THROW ); |
| sal_Int16 nListenerChoice = xListener->copyRowError( _rEvent ); |
| switch ( nListenerChoice ) |
| { |
| case CopyTableContinuation::Proceed: return true; // continue copying |
| case CopyTableContinuation::CallNextHandler: continue; // continue the loop, ask next listener |
| case CopyTableContinuation::Cancel: return false; // cancel copying |
| case CopyTableContinuation::AskUser: break; // stop asking the listeners, ask the user |
| |
| default: |
| OSL_ENSURE( false, "CopyTableWizard::impl_processCopyError_nothrow: invalid listener response!" ); |
| // ask next listener |
| continue; |
| } |
| } |
| } |
| catch( const Exception& ) |
| { |
| DBG_UNHANDLED_EXCEPTION(); |
| } |
| |
| // no listener felt responsible for the error, or a listener told to ask the user |
| |
| try |
| { |
| SQLContext aError; |
| aError.Context = *this; |
| aError.Message = String( ModuleRes( STR_ERROR_OCCURED_WHILE_COPYING ) ); |
| |
| ::dbtools::SQLExceptionInfo aInfo( _rEvent.Error ); |
| if ( aInfo.isValid() ) |
| aError.NextException = _rEvent.Error; |
| else |
| { |
| // a non-SQL exception happend |
| Exception aException; |
| OSL_VERIFY( _rEvent.Error >>= aException ); |
| SQLContext aContext; |
| aContext.Context = aException.Context; |
| aContext.Message = aException.Message; |
| aContext.Details = _rEvent.Error.getValueTypeName(); |
| aError.NextException <<= aContext; |
| } |
| |
| ::rtl::Reference< ::comphelper::OInteractionRequest > xRequest( new ::comphelper::OInteractionRequest( makeAny( aError ) ) ); |
| |
| ::rtl::Reference< ::comphelper::OInteractionApprove > xYes = new ::comphelper::OInteractionApprove; |
| xRequest->addContinuation( xYes.get() ); |
| xRequest->addContinuation( new ::comphelper::OInteractionDisapprove ); |
| |
| OSL_ENSURE( m_xInteractionHandler.is(), |
| "CopyTableWizard::impl_processCopyError_nothrow: we always should have an interaction handler!" ); |
| if ( m_xInteractionHandler.is() ) |
| m_xInteractionHandler->handle( xRequest.get() ); |
| |
| if ( xYes->wasSelected() ) |
| // continue copying |
| return true; |
| } |
| catch( const Exception& ) |
| { |
| DBG_UNHANDLED_EXCEPTION(); |
| } |
| |
| // cancel copying |
| return false; |
| } |
| |
| //------------------------------------------------------------------------- |
| void CopyTableWizard::impl_copyRows_throw( const Reference< XResultSet >& _rxSourceResultSet, |
| const Reference< XPropertySet >& _rxDestTable ) |
| { |
| OSL_PRECOND( m_xDestConnection.is(), "CopyTableWizard::impl_copyRows_throw: illegal call!" ); |
| if ( !m_xDestConnection.is() ) |
| throw RuntimeException( ::rtl::OUString(), *this ); |
| |
| Reference< XDatabaseMetaData > xDestMetaData( m_xDestConnection->getMetaData(), UNO_QUERY_THROW ); |
| |
| const OCopyTableWizard& rWizard = impl_getDialog_throw(); |
| ODatabaseExport::TPositions aColumnMapping = rWizard.GetColumnPositions(); |
| bool bAutoIncrement = rWizard.shouldCreatePrimaryKey(); |
| |
| Reference< XRow > xRow ( _rxSourceResultSet, UNO_QUERY_THROW ); |
| Reference< XRowLocate > xRowLocate ( _rxSourceResultSet, UNO_QUERY_THROW ); |
| |
| Reference< XResultSetMetaDataSupplier > xSuppResMeta( _rxSourceResultSet, UNO_QUERY_THROW ); |
| Reference< XResultSetMetaData> xMeta( xSuppResMeta->getMetaData() ); |
| |
| // we need a vector which all types |
| sal_Int32 nCount = xMeta->getColumnCount(); |
| ::std::vector< sal_Int32 > aSourceColTypes; |
| aSourceColTypes.reserve( nCount + 1 ); |
| aSourceColTypes.push_back( -1 ); // just to avoid a everytime i-1 call |
| |
| ::std::vector< sal_Int32 > aSourcePrec; |
| aSourcePrec.reserve( nCount + 1 ); |
| aSourcePrec.push_back( -1 ); // just to avoid a everytime i-1 call |
| |
| for ( sal_Int32 k=1; k <= nCount; ++k ) |
| { |
| aSourceColTypes.push_back( xMeta->getColumnType( k ) ); |
| aSourcePrec.push_back( xMeta->getPrecision( k ) ); |
| } |
| |
| // now create, fill and execute the prepared statement |
| Reference< XPreparedStatement > xStatement( ODatabaseExport::createPreparedStatment( xDestMetaData, _rxDestTable, aColumnMapping ), UNO_SET_THROW ); |
| Reference< XParameters > xStatementParams( xStatement, UNO_QUERY_THROW ); |
| |
| const bool bSelectedRecordsOnly = m_aSourceSelection.getLength() != 0; |
| const Any* pSelectedRow = m_aSourceSelection.getConstArray(); |
| const Any* pSelEnd = pSelectedRow + m_aSourceSelection.getLength(); |
| |
| sal_Int32 nRowCount = 0; |
| bool bContinue = false; |
| |
| CopyTableRowEvent aCopyEvent; |
| aCopyEvent.Source = *this; |
| aCopyEvent.SourceData = _rxSourceResultSet; |
| |
| do // loop as long as there are more rows or the selection ends |
| { |
| bContinue = false; |
| if ( bSelectedRecordsOnly ) |
| { |
| if ( pSelectedRow != pSelEnd ) |
| { |
| if ( m_bSourceSelectionBookmarks ) |
| { |
| bContinue = xRowLocate->moveToBookmark( *pSelectedRow ); |
| } |
| else |
| { |
| sal_Int32 nPos = 0; |
| OSL_VERIFY( *pSelectedRow >>= nPos ); |
| bContinue = _rxSourceResultSet->absolute( nPos ); |
| } |
| ++pSelectedRow; |
| } |
| } |
| else |
| bContinue = _rxSourceResultSet->next(); |
| |
| if ( !bContinue ) |
| { |
| break; |
| } |
| |
| ++nRowCount; |
| sal_Bool bInsertAutoIncrement = sal_True; |
| ODatabaseExport::TPositions::const_iterator aPosIter = aColumnMapping.begin(); |
| ODatabaseExport::TPositions::const_iterator aPosEnd = aColumnMapping.end(); |
| |
| aCopyEvent.Error.clear(); |
| try |
| { |
| // notify listeners |
| m_aCopyTableListeners.notifyEach( &XCopyTableListener::copyingRow, aCopyEvent ); |
| |
| sal_Int32 nDestColumn( 0 ); |
| sal_Int32 nSourceColumn( 1 ); |
| ValueTransfer aTransfer( nSourceColumn, nDestColumn, aSourceColTypes, xRow, xStatementParams ); |
| |
| for ( ; aPosIter != aPosEnd; ++aPosIter ) |
| { |
| nDestColumn = aPosIter->first; |
| if ( nDestColumn == COLUMN_POSITION_NOT_FOUND ) |
| { |
| ++nSourceColumn; |
| // otherwise we don't get the correct value when only the 2nd source column was selected |
| continue; |
| } |
| |
| if ( bAutoIncrement && bInsertAutoIncrement ) |
| { |
| xStatementParams->setInt( 1, nRowCount ); |
| bInsertAutoIncrement = sal_False; |
| continue; |
| } |
| |
| if ( ( nSourceColumn < 1 ) || ( nSourceColumn >= (sal_Int32)aSourceColTypes.size() ) ) |
| { // ( we have to check here against 1 because the parameters are 1 based) |
| ::dbtools::throwSQLException( |
| ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Internal error: invalid column type index." ) ), |
| ::dbtools::SQL_INVALID_DESCRIPTOR_INDEX, |
| *this |
| ); |
| } |
| |
| switch ( aSourceColTypes[ nSourceColumn ] ) |
| { |
| case DataType::DOUBLE: |
| case DataType::REAL: |
| aTransfer.transferValue( &XRow::getDouble, &XParameters::setDouble ); |
| break; |
| |
| case DataType::CHAR: |
| case DataType::VARCHAR: |
| case DataType::LONGVARCHAR: |
| case DataType::DECIMAL: |
| case DataType::NUMERIC: |
| aTransfer.transferComplexValue( &XRow::getString, &XParameters::setString ); |
| break; |
| |
| case DataType::BIGINT: |
| aTransfer.transferValue( &XRow::getLong, &XParameters::setLong ); |
| break; |
| |
| case DataType::FLOAT: |
| aTransfer.transferValue( &XRow::getFloat, &XParameters::setFloat ); |
| break; |
| |
| case DataType::LONGVARBINARY: |
| case DataType::BINARY: |
| case DataType::VARBINARY: |
| aTransfer.transferComplexValue( &XRow::getBytes, &XParameters::setBytes ); |
| break; |
| |
| case DataType::DATE: |
| aTransfer.transferComplexValue( &XRow::getDate, &XParameters::setDate ); |
| break; |
| |
| case DataType::TIME: |
| aTransfer.transferComplexValue( &XRow::getTime, &XParameters::setTime ); |
| break; |
| |
| case DataType::TIMESTAMP: |
| aTransfer.transferComplexValue( &XRow::getTimestamp, &XParameters::setTimestamp ); |
| break; |
| |
| case DataType::BIT: |
| if ( aSourcePrec[nSourceColumn] > 1 ) |
| { |
| aTransfer.transferComplexValue( &XRow::getBytes, &XParameters::setBytes ); |
| break; |
| } |
| // run through |
| case DataType::BOOLEAN: |
| aTransfer.transferValue( &XRow::getBoolean, &XParameters::setBoolean ); |
| break; |
| |
| case DataType::TINYINT: |
| aTransfer.transferValue( &XRow::getByte, &XParameters::setByte ); |
| break; |
| |
| case DataType::SMALLINT: |
| aTransfer.transferValue( &XRow::getShort, &XParameters::setShort ); |
| break; |
| |
| case DataType::INTEGER: |
| aTransfer.transferValue( &XRow::getInt, &XParameters::setInt ); |
| break; |
| |
| case DataType::BLOB: |
| aTransfer.transferComplexValue( &XRow::getBlob, &XParameters::setBlob ); |
| break; |
| |
| case DataType::CLOB: |
| aTransfer.transferComplexValue( &XRow::getClob, &XParameters::setClob ); |
| break; |
| |
| default: |
| { |
| ::rtl::OUString aMessage( String( ModuleRes( STR_CTW_UNSUPPORTED_COLUMN_TYPE ) ) ); |
| |
| aMessage.replaceAt( aMessage.indexOfAsciiL( "$type$", 6 ), 6, ::rtl::OUString::valueOf( aSourceColTypes[ nSourceColumn ] ) ); |
| aMessage.replaceAt( aMessage.indexOfAsciiL( "$pos$", 5 ), 5, ::rtl::OUString::valueOf( nSourceColumn ) ); |
| |
| ::dbtools::throwSQLException( |
| aMessage, |
| ::dbtools::SQL_INVALID_SQL_DATA_TYPE, |
| *this |
| ); |
| } |
| } |
| ++nSourceColumn; |
| } |
| xStatement->executeUpdate(); |
| |
| // notify listeners |
| m_aCopyTableListeners.notifyEach( &XCopyTableListener::copiedRow, aCopyEvent ); |
| } |
| catch( const Exception& ) |
| { |
| aCopyEvent.Error = ::cppu::getCaughtException(); |
| } |
| |
| if ( aCopyEvent.Error.hasValue() ) |
| bContinue = impl_processCopyError_nothrow( aCopyEvent ); |
| } |
| while( bContinue ); |
| } |
| //------------------------------------------------------------------------- |
| void CopyTableWizard::impl_doCopy_nothrow() |
| { |
| Any aError; |
| |
| try |
| { |
| OCopyTableWizard& rWizard( impl_getDialog_throw() ); |
| |
| WaitObject aWO( rWizard.GetParent() ); |
| Reference< XPropertySet > xTable; |
| |
| switch ( rWizard.getOperation() ) |
| { |
| case CopyTableOperation::CopyDefinitionOnly: |
| case CopyTableOperation::CopyDefinitionAndData: |
| { |
| xTable = rWizard.createTable(); |
| |
| if( !xTable.is() ) |
| { |
| OSL_ENSURE( false, "CopyTableWizard::impl_doCopy_nothrow: createTable should throw here, shouldn't it?" ); |
| break; |
| } |
| |
| if( CopyTableOperation::CopyDefinitionOnly == rWizard.getOperation() ) |
| break; |
| } |
| // run through |
| |
| case CopyTableOperation::AppendData: |
| { |
| |
| if ( !xTable.is() ) |
| { |
| xTable = rWizard.createTable(); |
| if ( !xTable.is() ) |
| { |
| OSL_ENSURE( false, "CopyTableWizard::impl_doCopy_nothrow: createTable should throw here, shouldn't it?" ); |
| break; |
| } |
| } |
| |
| ::utl::SharedUNOComponent< XPreparedStatement > xSourceStatement; |
| ::utl::SharedUNOComponent< XResultSet > xSourceResultSet; |
| |
| if ( m_xSourceResultSet.is() ) |
| { |
| xSourceResultSet.reset( m_xSourceResultSet, ::utl::SharedUNOComponent< XResultSet >::NoTakeOwnership ); |
| } |
| else |
| { |
| const bool bIsSameConnection = ( m_xSourceConnection.getTyped() == m_xDestConnection.getTyped() ); |
| const bool bIsTable = ( CommandType::TABLE == m_nCommandType ); |
| bool bDone = false; |
| if ( bIsSameConnection && bIsTable ) |
| { |
| // try whether the server supports copying via SQL |
| try |
| { |
| m_xDestConnection->createStatement()->executeUpdate( impl_getServerSideCopyStatement_throw(xTable) ); |
| bDone = true; |
| } |
| catch( const Exception& ) |
| { |
| // this is allowed. |
| } |
| } |
| |
| if ( !bDone ) |
| { |
| xSourceStatement.set( impl_createSourceStatement_throw(), UNO_SET_THROW ); |
| xSourceResultSet.set( xSourceStatement->executeQuery(), UNO_SET_THROW ); |
| } |
| } |
| |
| if ( xSourceResultSet.is() ) |
| impl_copyRows_throw( xSourceResultSet, xTable ); |
| } |
| break; |
| |
| case CopyTableOperation::CreateAsView: |
| rWizard.createView(); |
| break; |
| |
| default: |
| OSL_ENSURE( false, "CopyTableWizard::impl_doCopy_nothrow: What operation, please?" ); |
| break; |
| } |
| } |
| catch( const Exception& ) |
| { |
| aError = ::cppu::getCaughtException(); |
| |
| // silence the error of the user cancelling the parameter's dialog |
| SQLException aSQLError; |
| if ( ( aError >>= aSQLError ) && ( aSQLError.ErrorCode == ::dbtools::ParameterInteractionCancelled ) ) |
| { |
| aError.clear(); |
| m_nOverrideExecutionResult = RET_CANCEL; |
| } |
| } |
| |
| if ( aError.hasValue() && m_xInteractionHandler.is() ) |
| { |
| try |
| { |
| ::rtl::Reference< ::comphelper::OInteractionRequest > xRequest( new ::comphelper::OInteractionRequest( aError ) ); |
| m_xInteractionHandler->handle( xRequest.get() ); |
| } |
| catch( const Exception& ) |
| { |
| DBG_UNHANDLED_EXCEPTION(); |
| } |
| } |
| } |
| // ----------------------------------------------------------------------------- |
| ::rtl::OUString CopyTableWizard::impl_getServerSideCopyStatement_throw(const Reference< XPropertySet >& _xTable) |
| { |
| const Reference<XColumnsSupplier> xDestColsSup(_xTable,UNO_QUERY_THROW); |
| const Sequence< ::rtl::OUString> aDestColumnNames = xDestColsSup->getColumns()->getElementNames(); |
| const Sequence< ::rtl::OUString > aColumnNames = m_pSourceObject->getColumnNames(); |
| const Reference< XDatabaseMetaData > xDestMetaData( m_xDestConnection->getMetaData(), UNO_QUERY_THROW ); |
| const ::rtl::OUString sQuote = xDestMetaData->getIdentifierQuoteString(); |
| ::rtl::OUStringBuffer sColumns; |
| // 1st check if the columns matching |
| const OCopyTableWizard& rWizard = impl_getDialog_throw(); |
| ODatabaseExport::TPositions aColumnMapping = rWizard.GetColumnPositions(); |
| ODatabaseExport::TPositions::const_iterator aPosIter = aColumnMapping.begin(); |
| for ( sal_Int32 i = 0; aPosIter != aColumnMapping.end() ; ++aPosIter,++i ) |
| { |
| if ( COLUMN_POSITION_NOT_FOUND != aPosIter->second ) |
| { |
| if ( sColumns.getLength() ) |
| sColumns.appendAscii(","); |
| sColumns.append(sQuote); |
| sColumns.append(aDestColumnNames[aPosIter->second - 1]); |
| sColumns.append(sQuote); |
| } |
| } // for ( ; aPosIter != aColumnMapping.end() ; ++aPosIter ) |
| ::rtl::OUStringBuffer sSql; |
| sSql.appendAscii("INSERT INTO "); |
| const ::rtl::OUString sComposedTableName = ::dbtools::composeTableName( xDestMetaData, _xTable, ::dbtools::eInDataManipulation, false, false, true ); |
| sSql.append( sComposedTableName ); |
| sSql.appendAscii(" ( "); |
| sSql.append( sColumns ); |
| sSql.appendAscii(" ) ( "); |
| sSql.append( m_pSourceObject->getSelectStatement()); |
| sSql.appendAscii(" )"); |
| |
| return sSql.makeStringAndClear(); |
| } |
| //------------------------------------------------------------------------- |
| void SAL_CALL CopyTableWizard::initialize( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException) |
| { |
| ::osl::MutexGuard aGuard( m_aMutex ); |
| if ( isInitialized() ) |
| throw AlreadyInitializedException( ::rtl::OUString(), *this ); |
| |
| sal_Int32 nArgCount( _rArguments.getLength() ); |
| if ( ( nArgCount != 2 ) && ( nArgCount != 3 ) ) |
| throw IllegalArgumentException( |
| String( ModuleRes( STR_CTW_ILLEGAL_PARAMETER_COUNT ) ), |
| *this, |
| 1 |
| ); |
| |
| try |
| { |
| if ( nArgCount == 3 ) |
| { // ->createWithInteractionHandler |
| if ( !( _rArguments[2] >>= m_xInteractionHandler ) ) |
| throw IllegalArgumentException( |
| String(ModuleRes( STR_CTW_ERROR_INVALID_INTERACTIONHANDLER )), |
| *this, |
| 3 |
| ); |
| } |
| if ( !m_xInteractionHandler.is() ) |
| m_xInteractionHandler.set( m_aContext.createComponent( "com.sun.star.task.InteractionHandler" ), UNO_QUERY_THROW ); |
| |
| InteractionHandler xSourceDocHandler; |
| Reference< XPropertySet > xSourceDescriptor( impl_ensureDataAccessDescriptor_throw( _rArguments, 0, m_xSourceConnection, xSourceDocHandler ) ); |
| impl_checkForUnsupportedSettings_throw( xSourceDescriptor ); |
| m_pSourceObject = impl_extractSourceObject_throw( xSourceDescriptor, m_nCommandType ); |
| impl_extractSourceResultSet_throw( xSourceDescriptor ); |
| |
| InteractionHandler xDestDocHandler; |
| impl_ensureDataAccessDescriptor_throw( _rArguments, 1, m_xDestConnection, xDestDocHandler ); |
| |
| if ( xDestDocHandler.is() && !m_xInteractionHandler.is() ) |
| m_xInteractionHandler = xDestDocHandler; |
| } |
| catch( const RuntimeException& ) { throw; } |
| catch( const IllegalArgumentException& ) { throw; } |
| catch( const SQLException& ) { throw; } |
| catch( const Exception& ) |
| { |
| throw WrappedTargetException( |
| String( ModuleRes( STR_CTW_ERROR_DURING_INITIALIZATION ) ), |
| *this, |
| ::cppu::getCaughtException() |
| ); |
| } |
| } |
| |
| //------------------------------------------------------------------------- |
| ::cppu::IPropertyArrayHelper& CopyTableWizard::getInfoHelper() |
| { |
| return *getArrayHelper(); |
| } |
| |
| //------------------------------------------------------------------------------ |
| ::cppu::IPropertyArrayHelper* CopyTableWizard::createArrayHelper( ) const |
| { |
| Sequence< Property > aProps; |
| describeProperties( aProps ); |
| return new ::cppu::OPropertyArrayHelper( aProps ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| Dialog* CopyTableWizard::createDialog( Window* _pParent ) |
| { |
| OSL_PRECOND( isInitialized(), "CopyTableWizard::createDialog: not initialized!" ); |
| // this should have been prevented in ::execute already |
| |
| OCopyTableWizard* pWizard = new OCopyTableWizard( |
| _pParent, |
| m_sDestinationTable, |
| m_nOperation, |
| *m_pSourceObject, |
| m_xSourceConnection.getTyped(), |
| m_xDestConnection.getTyped(), |
| m_aContext.getLegacyServiceFactory(), |
| m_xInteractionHandler |
| ); |
| |
| impl_attributesToDialog_nothrow( *pWizard ); |
| |
| return pWizard; |
| } |
| |
| //------------------------------------------------------------------------------ |
| void CopyTableWizard::executedDialog( sal_Int16 _nExecutionResult ) |
| { |
| CopyTableWizard_DialogBase::executedDialog( _nExecutionResult ); |
| |
| if ( _nExecutionResult == RET_OK ) |
| impl_doCopy_nothrow(); |
| |
| // do this after impl_doCopy_nothrow: The attributes may change during copying, for instance |
| // if the user entered an unqualified table name |
| impl_dialogToAttributes_nothrow( impl_getDialog_throw() ); |
| } |
| |
| //........................................................................ |
| } // namespace dbaui |
| //........................................................................ |
| |
| extern "C" void SAL_CALL createRegistryInfo_CopyTableWizard() |
| { |
| static ::dbaui::OMultiInstanceAutoRegistration< ::dbaui::CopyTableWizard > aAutoRegistration; |
| } |