xref: /core/dbaccess/source/ui/uno/copytablewizard.cxx (revision 6f1508f4de761e564146f3111345270403838468)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <memory>
21 #include <strings.hrc>
22 #include <strings.hxx>
23 #include <core_resource.hxx>
24 #include <WCopyTable.hxx>
25 
26 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
27 #include <com/sun/star/sdb/application/XCopyTableWizard.hpp>
28 #include <com/sun/star/sdb/application/CopyTableContinuation.hpp>
29 #include <com/sun/star/sdb/application/CopyTableOperation.hpp>
30 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
31 #include <com/sun/star/lang/NotInitializedException.hpp>
32 #include <com/sun/star/sdbc/XDataSource.hpp>
33 #include <com/sun/star/sdbc/DataType.hpp>
34 #include <com/sun/star/container/XNameAccess.hpp>
35 #include <com/sun/star/container/XChild.hpp>
36 #include <com/sun/star/task/InteractionHandler.hpp>
37 #include <com/sun/star/frame/XModel.hpp>
38 #include <com/sun/star/sdb/DatabaseContext.hpp>
39 #include <com/sun/star/sdb/XDocumentDataSource.hpp>
40 #include <com/sun/star/sdb/XCompletedConnection.hpp>
41 #include <com/sun/star/sdb/CommandType.hpp>
42 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
43 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
44 #include <com/sun/star/lang/DisposedException.hpp>
45 #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
46 #include <com/sun/star/sdbc/XParameters.hpp>
47 #include <com/sun/star/sdbc/XRow.hpp>
48 #include <com/sun/star/sdbcx/XRowLocate.hpp>
49 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
50 #include <com/sun/star/sdb/SQLContext.hpp>
51 #include <com/sun/star/sdbc/DriverManager.hpp>
52 #include <com/sun/star/sdbc/ConnectionPool.hpp>
53 
54 #include <comphelper/processfactory.hxx>
55 #include <comphelper/interaction.hxx>
56 #include <comphelper/namedvaluecollection.hxx>
57 #include <comphelper/proparrhlp.hxx>
58 #include <connectivity/dbexception.hxx>
59 #include <connectivity/dbtools.hxx>
60 #include <cppuhelper/exc_hlp.hxx>
61 #include <cppuhelper/implbase.hxx>
62 #include <comphelper/interfacecontainer3.hxx>
63 #include <o3tl/safeint.hxx>
64 #include <rtl/ustrbuf.hxx>
65 #include <sal/log.hxx>
66 #include <svtools/genericunodialog.hxx>
67 #include <toolkit/helper/vclunohelper.hxx>
68 #include <comphelper/diagnose_ex.hxx>
69 #include <unotools/sharedunocomponent.hxx>
70 #include <vcl/svapp.hxx>
71 
72 namespace dbaui
73 {
74 
75     using ::com::sun::star::uno::Reference;
76     using ::com::sun::star::uno::XInterface;
77     using ::com::sun::star::uno::UNO_QUERY;
78     using ::com::sun::star::uno::UNO_QUERY_THROW;
79     using ::com::sun::star::uno::UNO_SET_THROW;
80     using ::com::sun::star::uno::Exception;
81     using ::com::sun::star::uno::RuntimeException;
82     using ::com::sun::star::uno::Any;
83     using ::com::sun::star::uno::Sequence;
84     using ::com::sun::star::uno::XComponentContext;
85     using ::com::sun::star::beans::XPropertySetInfo;
86     using ::com::sun::star::lang::XMultiServiceFactory;
87     using ::com::sun::star::beans::Property;
88     using ::com::sun::star::sdb::application::XCopyTableWizard;
89     using ::com::sun::star::sdb::application::XCopyTableListener;
90     using ::com::sun::star::sdb::application::CopyTableRowEvent;
91     using ::com::sun::star::beans::Optional;
92     using ::com::sun::star::lang::IllegalArgumentException;
93     using ::com::sun::star::ucb::AlreadyInitializedException;
94     using ::com::sun::star::beans::XPropertySet;
95     using ::com::sun::star::lang::NotInitializedException;
96     using ::com::sun::star::lang::XServiceInfo;
97     using ::com::sun::star::sdbc::XConnection;
98     using ::com::sun::star::sdbc::XDataSource;
99     using ::com::sun::star::container::XNameAccess;
100     using ::com::sun::star::container::XChild;
101     using ::com::sun::star::task::InteractionHandler;
102     using ::com::sun::star::task::XInteractionHandler;
103     using ::com::sun::star::frame::XModel;
104     using ::com::sun::star::sdb::DatabaseContext;
105     using ::com::sun::star::sdb::XDatabaseContext;
106     using ::com::sun::star::sdb::XDocumentDataSource;
107     using ::com::sun::star::sdb::XCompletedConnection;
108     using ::com::sun::star::lang::WrappedTargetException;
109     using ::com::sun::star::sdbcx::XTablesSupplier;
110     using ::com::sun::star::sdb::XQueriesSupplier;
111     using ::com::sun::star::lang::DisposedException;
112     using ::com::sun::star::sdbc::XPreparedStatement;
113     using ::com::sun::star::sdb::XSingleSelectQueryComposer;
114     using ::com::sun::star::sdbc::XDatabaseMetaData;
115     using ::com::sun::star::sdbcx::XColumnsSupplier;
116     using ::com::sun::star::sdbc::XParameters;
117     using ::com::sun::star::sdbc::XResultSet;
118     using ::com::sun::star::sdbc::XRow;
119     using ::com::sun::star::sdbcx::XRowLocate;
120     using ::com::sun::star::sdbc::XResultSetMetaDataSupplier;
121     using ::com::sun::star::sdbc::XResultSetMetaData;
122     using ::com::sun::star::sdbc::SQLException;
123     using ::com::sun::star::sdb::SQLContext;
124     using ::com::sun::star::sdbc::ConnectionPool;
125     using ::com::sun::star::sdbc::XDriverManager;
126     using ::com::sun::star::sdbc::DriverManager;
127     using ::com::sun::star::beans::PropertyValue;
128 
129     namespace CopyTableOperation = ::com::sun::star::sdb::application::CopyTableOperation;
130     namespace CopyTableContinuation = ::com::sun::star::sdb::application::CopyTableContinuation;
131     namespace CommandType = ::com::sun::star::sdb::CommandType;
132     namespace DataType = ::com::sun::star::sdbc::DataType;
133 
134     typedef ::utl::SharedUNOComponent< XConnection >    SharedConnection;
135 
136     // CopyTableWizard
137     typedef ::svt::OGenericUnoDialog        CopyTableWizard_DialogBase;
138     typedef ::cppu::ImplInheritanceHelper<   CopyTableWizard_DialogBase
139                                          ,   XCopyTableWizard
140                                          >   CopyTableWizard_Base;
141 
142     namespace {
143 
144     class CopyTableWizard
145             :public CopyTableWizard_Base
146             ,public ::comphelper::OPropertyArrayUsageHelper< CopyTableWizard >
147     {
148     public:
149         // XServiceInfo
150         virtual OUString SAL_CALL getImplementationName() override;
151         virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
152 
153         // XCopyTableWizard
154         virtual ::sal_Int16 SAL_CALL getOperation() override;
155         virtual void SAL_CALL setOperation( ::sal_Int16 _operation ) override;
156         virtual OUString SAL_CALL getDestinationTableName() override;
157         virtual void SAL_CALL setDestinationTableName( const OUString& _destinationTableName ) override;
158         virtual Optional< OUString > SAL_CALL getCreatePrimaryKey() override;
159         virtual void SAL_CALL setCreatePrimaryKey( const Optional< OUString >& _newPrimaryKey ) override;
160         virtual sal_Bool SAL_CALL getUseHeaderLineAsColumnNames() override;
161         virtual void SAL_CALL setUseHeaderLineAsColumnNames( sal_Bool _bUseHeaderLineAsColumnNames ) override;
162         virtual void SAL_CALL addCopyTableListener( const Reference< XCopyTableListener >& Listener ) override;
163         virtual void SAL_CALL removeCopyTableListener( const Reference< XCopyTableListener >& Listener ) override;
164 
165         // XCopyTableWizard::XExecutableDialog
166         virtual void SAL_CALL setTitle( const OUString& aTitle ) override;
167         virtual ::sal_Int16 SAL_CALL execute(  ) override;
168 
169         // XInitialization
170         virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) override;
171 
172         // XPropertySet
173         virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
174         virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
175 
176         // OPropertyArrayUsageHelper
177         virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
178 
179     public:
getMutex()180         ::osl::Mutex&   getMutex() { return m_aMutex; }
isInitialized() const181         bool            isInitialized() const { return m_xSourceConnection.is() && m_pSourceObject && m_xDestConnection.is(); }
182 
183         explicit CopyTableWizard( const Reference< XComponentContext >& _rxORB );
184         virtual ~CopyTableWizard() override;
185 
186     protected:
187         // OGenericUnoDialog overridables
188         virtual std::unique_ptr<weld::DialogController> createDialog(const css::uno::Reference<css::awt::XWindow>& rParent) override;
189         virtual void executedDialog( sal_Int16 _nExecutionResult ) override;
190 
191     private:
192         /// ensures our current attribute values are reflected in the dialog
193         void    impl_attributesToDialog_nothrow( OCopyTableWizard& _rDialog ) const;
194 
195         /// ensures the current dialog settings are reflected in our attributes
196         void    impl_dialogToAttributes_nothrow( const OCopyTableWizard& _rDialog );
197 
198         /** returns our typed dialog
199 
200             @throws css::uno::RuntimeException
201                 if we don't have a dialog at the moment the method is called
202         */
203         OCopyTableWizard&
204                 impl_getDialog_throw();
205 
206         /** ensures the given argument sequence contains a valid data access descriptor at the given position
207             @param _rAllArgs
208                 the arguments as passed to ->initialize
209             @param _nArgPos
210                 the position within ->_rAllArgs which contains the data access descriptor
211             @param _out_rxConnection
212                 will, upon successful return, contain the connection for the data source
213             @param _out_rxDocInteractionHandler
214                 will, upon successful return, contain the interaction handler which could
215                 be deduced from database document described by the descriptor, if any.
216                 (It is possible that the descriptor does not allow to deduce a database document,
217                 in which case <code>_out_rxDocInteractionHandler</code> will be <NULL/>.)
218             @return the data access descriptor
219         */
220         Reference< XPropertySet >
221                 impl_ensureDataAccessDescriptor_throw(
222                     const Sequence< Any >& _rAllArgs,
223                     const sal_Int16 _nArgPos,
224                     SharedConnection& _out_rxConnection,
225                     Reference< XInteractionHandler >& _out_rxDocInteractionHandler
226                 ) const;
227 
228         /** extracts the source object (table or query) described by the given descriptor,
229             relative to m_xSourceConnection
230         */
231         std::unique_ptr< ICopyTableSourceObject >
232                 impl_extractSourceObject_throw(
233                     const Reference< XPropertySet >& _rxDescriptor,
234                     sal_Int32& _out_rCommandType
235                 ) const;
236 
237         /** extracts the result set to copy records from, and the selection-related aspects, if any.
238 
239             Effectively, this method extracts m_xSourceResultSet, m_aSourceSelection, and m_bSourceSelectionBookmarks.
240 
241             If an inconsistent/insufficient sub set of those properties is present in the descriptor, and exception
242             is thrown.
243         */
244         void    impl_extractSourceResultSet_throw(
245                     const Reference< XPropertySet >& i_rDescriptor
246                 );
247 
248         /** checks whether the given copy source descriptor contains settings which are not
249             supported (yet)
250 
251             Throws an IllegalArgumentException if the descriptor contains a valid setting, which is
252             not yet supported.
253         */
254         void    impl_checkForUnsupportedSettings_throw(
255             const Reference< XPropertySet >& _rxSourceDescriptor ) const;
256 
257         /** obtains the connection described by the given data access descriptor
258 
259             If needed and possible, the method will ask the user, using the interaction
260             handler associated with the database described by the descriptor.
261 
262             All errors are handled with the InteractionHandler associated with the data source,
263             if there is one. Else, they will be silenced (but asserted in non-product builds).
264 
265             @param _rxDataSourceDescriptor
266                 the data access descriptor describing the data source whose connection
267                 should be obtained. Must not be <NULL/>.
268             @param _out_rxDocInteractionHandler
269                 the interaction handler which could be deduced from the descriptor
270 
271             @throws RuntimeException
272                 if anything goes seriously wrong.
273         */
274         SharedConnection
275                 impl_extractConnection_throw(
276                     const Reference< XPropertySet >& _rxDataSourceDescriptor,
277                     Reference< XInteractionHandler >& _out_rxDocInteractionHandler
278                 ) const;
279 
280         /** actually copies the table
281 
282             This method is called after the dialog has been successfully executed.
283         */
284         void    impl_doCopy_nothrow();
285 
286         /** creates the INSERT INTO statement
287             @param  _xTable The destination table.
288         */
289         OUString impl_getServerSideCopyStatement_throw( const Reference< XPropertySet >& _xTable );
290 
291         /** creates the statement which, when executed, will produce the source data to copy
292 
293             If the source object refers to a query which contains parameters, those parameters
294             are filled in, using an interaction handler.
295         */
296         ::utl::SharedUNOComponent< XPreparedStatement >
297                 impl_createSourceStatement_throw() const;
298 
299         /** copies the data rows from the given source result set to the given destination table
300         */
301         void    impl_copyRows_throw(
302                     const Reference< XResultSet >& _rxSourceResultSet,
303                     const Reference< XPropertySet >& _rxDestTable
304                 );
305 
306         /** processes an error which occurred during copying
307 
308             First, all listeners are ask. If a listener tells to cancel or continue copying, this is reported to the
309             method's caller. If a listener tells to ask the user, this is done, and the user's decision is
310             reported to the method's caller.
311 
312             @return
313                 <TRUE/> if and only if copying should be continued.
314         */
315         bool    impl_processCopyError_nothrow(
316                     const CopyTableRowEvent& _rEvent );
317 
318 private:
319         Reference<XComponentContext>    m_xContext;
320 
321         // attributes
322         sal_Int16                       m_nOperation;
323         OUString                        m_sDestinationTable;
324         Optional< OUString >            m_aPrimaryKeyName;
325         bool                        m_bUseHeaderLineAsColumnNames;
326 
327         // source
328         SharedConnection                m_xSourceConnection;
329         sal_Int32                       m_nCommandType;
330         std::unique_ptr< ICopyTableSourceObject >
331                                         m_pSourceObject;
332         Reference< XResultSet >         m_xSourceResultSet;
333         Sequence< Any >                 m_aSourceSelection;
334         bool                        m_bSourceSelectionBookmarks;
335 
336         // destination
337         SharedConnection                m_xDestConnection;
338 
339         // other
340         Reference< XInteractionHandler > m_xInteractionHandler;
341         ::comphelper::OInterfaceContainerHelper3<XCopyTableListener>
342                                         m_aCopyTableListeners;
343         sal_Int16                       m_nOverrideExecutionResult;
344     };
345 
346 // MethodGuard
347 class CopyTableAccessGuard
348 {
349 public:
CopyTableAccessGuard(CopyTableWizard & _rWizard)350     explicit CopyTableAccessGuard( CopyTableWizard& _rWizard )
351         :m_rWizard( _rWizard )
352     {
353         m_rWizard.getMutex().acquire();
354         if ( !m_rWizard.isInitialized() )
355             throw NotInitializedException();
356     }
357 
~CopyTableAccessGuard()358     ~CopyTableAccessGuard()
359     {
360         m_rWizard.getMutex().release();
361     }
362 
363 private:
364     CopyTableWizard&    m_rWizard;
365 };
366 
367 }
368 
CopyTableWizard(const Reference<XComponentContext> & _rxORB)369 CopyTableWizard::CopyTableWizard( const Reference< XComponentContext >& _rxORB )
370     :CopyTableWizard_Base( _rxORB )
371     ,m_xContext( _rxORB )
372     ,m_nOperation( CopyTableOperation::CopyDefinitionAndData )
373     ,m_aPrimaryKeyName( false,  u"ID"_ustr )
374     ,m_bUseHeaderLineAsColumnNames( true )
375     ,m_nCommandType( CommandType::COMMAND )
376     ,m_bSourceSelectionBookmarks( true )
377     ,m_aCopyTableListeners( m_aMutex )
378     ,m_nOverrideExecutionResult( -1 )
379 {
380 }
381 
~CopyTableWizard()382 CopyTableWizard::~CopyTableWizard()
383 {
384     acquire();
385 
386     // protect some members whose dtor might potentially throw
387     try { m_xSourceConnection.clear();  }
388     catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("dbaccess"); }
389     try { m_xDestConnection.clear();  }
390     catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("dbaccess"); }
391 
392     // TODO: shouldn't we have explicit disposal support? If a listener is registered
393     // at our instance, and perhaps holds this our instance by a hard ref, then we'll never
394     // be destroyed.
395     // However, adding XComponent support to the GenericUNODialog probably requires
396     // some thinking - would it break existing clients which do not call a dispose, then?
397 }
398 
getImplementationName()399 OUString SAL_CALL CopyTableWizard::getImplementationName()
400 {
401     return u"org.openoffice.comp.dbu.CopyTableWizard"_ustr;
402 }
403 
getSupportedServiceNames()404 css::uno::Sequence<OUString> SAL_CALL CopyTableWizard::getSupportedServiceNames()
405 {
406     return { u"com.sun.star.sdb.application.CopyTableWizard"_ustr };
407 }
408 
getPropertySetInfo()409 Reference< XPropertySetInfo > SAL_CALL CopyTableWizard::getPropertySetInfo()
410 {
411     Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
412     return xInfo;
413 }
414 
getOperation()415 ::sal_Int16 SAL_CALL CopyTableWizard::getOperation()
416 {
417     CopyTableAccessGuard aGuard( *this );
418     return m_nOperation;
419 }
420 
setOperation(::sal_Int16 _operation)421 void SAL_CALL CopyTableWizard::setOperation( ::sal_Int16 _operation )
422 {
423     CopyTableAccessGuard aGuard( *this );
424 
425     if  (   ( _operation != CopyTableOperation::CopyDefinitionAndData )
426         &&  ( _operation != CopyTableOperation::CopyDefinitionOnly )
427         &&  ( _operation != CopyTableOperation::CreateAsView )
428         &&  ( _operation != CopyTableOperation::AppendData )
429         )
430         throw IllegalArgumentException( OUString(), *this, 1 );
431 
432     if  (   ( _operation == CopyTableOperation::CreateAsView )
433         &&  !OCopyTableWizard::supportsViews( m_xDestConnection )
434         )
435         throw IllegalArgumentException(
436             DBA_RES( STR_CTW_NO_VIEWS_SUPPORT ),
437             *this,
438             1
439         );
440 
441     m_nOperation = _operation;
442 }
443 
getDestinationTableName()444 OUString SAL_CALL CopyTableWizard::getDestinationTableName()
445 {
446     CopyTableAccessGuard aGuard( *this );
447     return m_sDestinationTable;
448 }
449 
setDestinationTableName(const OUString & _destinationTableName)450 void SAL_CALL CopyTableWizard::setDestinationTableName( const OUString& _destinationTableName )
451 {
452     CopyTableAccessGuard aGuard( *this );
453     m_sDestinationTable = _destinationTableName;
454 }
455 
getCreatePrimaryKey()456 Optional< OUString > SAL_CALL CopyTableWizard::getCreatePrimaryKey()
457 {
458     CopyTableAccessGuard aGuard( *this );
459     return m_aPrimaryKeyName;
460 }
461 
setCreatePrimaryKey(const Optional<OUString> & _newPrimaryKey)462 void SAL_CALL CopyTableWizard::setCreatePrimaryKey( const Optional< OUString >& _newPrimaryKey )
463 {
464     CopyTableAccessGuard aGuard( *this );
465 
466     if ( _newPrimaryKey.IsPresent && !OCopyTableWizard::supportsPrimaryKey( m_xDestConnection ) )
467         throw IllegalArgumentException(
468             DBA_RES( STR_CTW_NO_PRIMARY_KEY_SUPPORT ),
469             *this,
470             1
471         );
472 
473     m_aPrimaryKeyName = _newPrimaryKey;
474 }
475 
getUseHeaderLineAsColumnNames()476 sal_Bool SAL_CALL CopyTableWizard::getUseHeaderLineAsColumnNames()
477 {
478     CopyTableAccessGuard aGuard( *this );
479     return m_bUseHeaderLineAsColumnNames;
480 }
481 
setUseHeaderLineAsColumnNames(sal_Bool _bUseHeaderLineAsColumnNames)482 void SAL_CALL CopyTableWizard::setUseHeaderLineAsColumnNames( sal_Bool _bUseHeaderLineAsColumnNames )
483 {
484     CopyTableAccessGuard aGuard( *this );
485     m_bUseHeaderLineAsColumnNames = _bUseHeaderLineAsColumnNames;
486 }
487 
addCopyTableListener(const Reference<XCopyTableListener> & _rxListener)488 void SAL_CALL CopyTableWizard::addCopyTableListener( const Reference< XCopyTableListener >& _rxListener )
489 {
490     CopyTableAccessGuard aGuard( *this );
491     if ( _rxListener.is() )
492         m_aCopyTableListeners.addInterface( _rxListener );
493 }
494 
removeCopyTableListener(const Reference<XCopyTableListener> & _rxListener)495 void SAL_CALL CopyTableWizard::removeCopyTableListener( const Reference< XCopyTableListener >& _rxListener )
496 {
497     CopyTableAccessGuard aGuard( *this );
498     if ( _rxListener.is() )
499         m_aCopyTableListeners.removeInterface( _rxListener );
500 }
501 
setTitle(const OUString & _rTitle)502 void SAL_CALL CopyTableWizard::setTitle( const OUString& _rTitle )
503 {
504     CopyTableAccessGuard aGuard( *this );
505     CopyTableWizard_DialogBase::setTitle( _rTitle );
506 }
507 
execute()508 ::sal_Int16 SAL_CALL CopyTableWizard::execute(  )
509 {
510     CopyTableAccessGuard aGuard( *this );
511 
512     m_nOverrideExecutionResult = -1;
513     sal_Int16 nExecutionResult = CopyTableWizard_DialogBase::execute();
514     if ( m_nOverrideExecutionResult )
515         nExecutionResult = m_nOverrideExecutionResult;
516 
517     return nExecutionResult;
518 }
519 
impl_getDialog_throw()520 OCopyTableWizard& CopyTableWizard::impl_getDialog_throw()
521 {
522     OCopyTableWizard* pWizard = dynamic_cast<OCopyTableWizard*>(m_xDialog.get());
523     if ( !pWizard )
524         throw DisposedException( OUString(), *this );
525     return *pWizard;
526 }
527 
impl_attributesToDialog_nothrow(OCopyTableWizard & _rDialog) const528 void CopyTableWizard::impl_attributesToDialog_nothrow( OCopyTableWizard& _rDialog ) const
529 {
530     // primary key column
531     _rDialog.setCreatePrimaryKey( m_aPrimaryKeyName.IsPresent, m_aPrimaryKeyName.Value );
532     _rDialog.setUseHeaderLine(m_bUseHeaderLineAsColumnNames);
533 
534     // everything else was passed at construction time already
535 }
536 
impl_dialogToAttributes_nothrow(const OCopyTableWizard & _rDialog)537 void CopyTableWizard::impl_dialogToAttributes_nothrow( const OCopyTableWizard& _rDialog )
538 {
539     m_aPrimaryKeyName.IsPresent = _rDialog.shouldCreatePrimaryKey();
540     if ( m_aPrimaryKeyName.IsPresent )
541         m_aPrimaryKeyName.Value = _rDialog.getPrimaryKeyName();
542     else
543         m_aPrimaryKeyName.Value.clear();
544 
545     m_sDestinationTable = _rDialog.getName();
546 
547     m_nOperation = _rDialog.getOperation();
548     m_bUseHeaderLineAsColumnNames = _rDialog.UseHeaderLine();
549 }
550 
551 namespace
552 {
553     /** tries to obtain the InteractionHandler associated with a given data source
554 
555         If the data source is a sdb-level data source, it will have a DatabaseDocument associated
556         with it. This document may have an InteractionHandler used while loading it.
557 
558         @throws RuntimeException
559             if it occurs during invoking any of the data source's methods, or if any of the involved
560             components violates its contract by not providing the required interfaces
561     */
lcl_getInteractionHandler_throw(const Reference<XDataSource> & _rxDataSource,const Reference<XInteractionHandler> & _rFallback)562     Reference< XInteractionHandler > lcl_getInteractionHandler_throw( const Reference< XDataSource >& _rxDataSource, const Reference< XInteractionHandler >& _rFallback )
563     {
564         Reference< XInteractionHandler > xHandler( _rFallback );
565 
566         // try to obtain the document model
567         Reference< XModel > xDocumentModel;
568         Reference< XDocumentDataSource > xDocDataSource( _rxDataSource, UNO_QUERY );
569         if ( xDocDataSource.is() )
570             xDocumentModel.set( xDocDataSource->getDatabaseDocument(), UNO_QUERY_THROW );
571 
572         // see whether the document model can provide a handler
573         if ( xDocumentModel.is() )
574         {
575             xHandler = ::comphelper::NamedValueCollection::getOrDefault( xDocumentModel->getArgs(), u"InteractionHandler", xHandler );
576         }
577 
578         return xHandler;
579     }
580     /** tries to obtain the InteractionHandler associated with a given connection
581 
582         If the connection belongs to a sdb-level data source, then this data source
583         is examined for an interaction handler. Else, <NULL/> is returned.
584 
585         @throws RuntimeException
586             if it occurs during invoking any of the data source's methods, or if any of the involved
587             components violates its contract by not providing the required interfaces
588     */
lcl_getInteractionHandler_throw(const Reference<XConnection> & _rxConnection,const Reference<XInteractionHandler> & _rFallback)589     Reference< XInteractionHandler > lcl_getInteractionHandler_throw( const Reference< XConnection >& _rxConnection, const Reference< XInteractionHandler >& _rFallback )
590     {
591         // try whether there is a data source which the connection belongs to
592         Reference< XDataSource > xDataSource;
593         Reference< XChild > xAsChild( _rxConnection, UNO_QUERY );
594         if ( xAsChild.is() )
595             xDataSource.set(xAsChild->getParent(), css::uno::UNO_QUERY);
596 
597         if ( xDataSource.is() )
598             return lcl_getInteractionHandler_throw( xDataSource, _rFallback );
599 
600         return _rFallback;
601     }
602 }
603 
impl_ensureDataAccessDescriptor_throw(const Sequence<Any> & _rAllArgs,const sal_Int16 _nArgPos,SharedConnection & _out_rxConnection,Reference<XInteractionHandler> & _out_rxDocInteractionHandler) const604 Reference< XPropertySet > CopyTableWizard::impl_ensureDataAccessDescriptor_throw(
605     const Sequence< Any >& _rAllArgs, const sal_Int16 _nArgPos, SharedConnection& _out_rxConnection,
606     Reference< XInteractionHandler >& _out_rxDocInteractionHandler ) const
607 {
608     Reference< XPropertySet > xDescriptor;
609     _rAllArgs[ _nArgPos ] >>= xDescriptor;
610 
611     // the descriptor must be non-NULL, of course
612     bool bIsValid = xDescriptor.is();
613 
614     // it must support the proper service
615     if ( bIsValid )
616     {
617         Reference< XServiceInfo > xSI( xDescriptor, UNO_QUERY );
618         bIsValid =  (   xSI.is()
619                     &&  xSI->supportsService( u"com.sun.star.sdb.DataAccessDescriptor"_ustr ) );
620     }
621 
622     // it must be able to provide a connection
623     if ( bIsValid )
624     {
625         _out_rxConnection = impl_extractConnection_throw( xDescriptor, _out_rxDocInteractionHandler );
626         bIsValid = _out_rxConnection.is();
627     }
628 
629     if ( !bIsValid )
630     {
631         throw IllegalArgumentException(
632             DBA_RES( STR_CTW_INVALID_DATA_ACCESS_DESCRIPTOR ),
633             *const_cast< CopyTableWizard* >( this ),
634             _nArgPos + 1
635         );
636     }
637 
638     return xDescriptor;
639 }
640 
641 namespace
642 {
lcl_hasNonEmptyStringValue_throw(const Reference<XPropertySet> & _rxDescriptor,const Reference<XPropertySetInfo> & rxPSI,const OUString & _rPropertyName)643     bool lcl_hasNonEmptyStringValue_throw( const Reference< XPropertySet >& _rxDescriptor,
644         const Reference< XPropertySetInfo >& rxPSI, const OUString& _rPropertyName )
645     {
646         OUString sValue;
647         if ( rxPSI->hasPropertyByName( _rPropertyName ) )
648         {
649             OSL_VERIFY( _rxDescriptor->getPropertyValue( _rPropertyName ) >>= sValue );
650         }
651         return !sValue.isEmpty();
652     }
653 }
654 
impl_checkForUnsupportedSettings_throw(const Reference<XPropertySet> & _rxSourceDescriptor) const655 void CopyTableWizard::impl_checkForUnsupportedSettings_throw( const Reference< XPropertySet >& _rxSourceDescriptor ) const
656 {
657     OSL_PRECOND( _rxSourceDescriptor.is(), "CopyTableWizard::impl_checkForUnsupportedSettings_throw: illegal argument!" );
658     Reference< XPropertySetInfo > xPSI( _rxSourceDescriptor->getPropertySetInfo(), UNO_SET_THROW );
659     OUString sUnsupportedSetting;
660 
661     const OUString aSettings[] = {
662         PROPERTY_FILTER, PROPERTY_ORDER, PROPERTY_HAVING_CLAUSE, PROPERTY_GROUP_BY
663     };
664     for (const auto & aSetting : aSettings)
665     {
666         if ( lcl_hasNonEmptyStringValue_throw( _rxSourceDescriptor, xPSI, aSetting ) )
667         {
668             sUnsupportedSetting = aSetting;
669             break;
670         }
671     }
672 
673     if ( !sUnsupportedSetting.isEmpty() )
674     {
675         OUString sMessage(
676             DBA_RES(STR_CTW_ERROR_UNSUPPORTED_SETTING).
677             replaceFirst("$name$", sUnsupportedSetting));
678         throw IllegalArgumentException(
679             sMessage,
680             *const_cast< CopyTableWizard* >( this ),
681             1
682         );
683     }
684 
685 }
686 
impl_extractSourceObject_throw(const Reference<XPropertySet> & _rxDescriptor,sal_Int32 & _out_rCommandType) const687 std::unique_ptr< ICopyTableSourceObject > CopyTableWizard::impl_extractSourceObject_throw( const Reference< XPropertySet >& _rxDescriptor, sal_Int32& _out_rCommandType ) const
688 {
689     OSL_PRECOND( _rxDescriptor.is() && m_xSourceConnection.is(), "CopyTableWizard::impl_extractSourceObject_throw: illegal arguments!" );
690 
691     Reference< XPropertySetInfo > xPSI( _rxDescriptor->getPropertySetInfo(), UNO_SET_THROW );
692     if  (   !xPSI->hasPropertyByName( PROPERTY_COMMAND )
693         ||  !xPSI->hasPropertyByName( PROPERTY_COMMAND_TYPE )
694         )
695         throw IllegalArgumentException(u"Expecting a table or query specification."_ustr,
696                                        // TODO: resource
697                                        *const_cast< CopyTableWizard* >( this ), 1);
698 
699     OUString sCommand;
700     _out_rCommandType = CommandType::COMMAND;
701     OSL_VERIFY( _rxDescriptor->getPropertyValue( PROPERTY_COMMAND ) >>= sCommand );
702     OSL_VERIFY( _rxDescriptor->getPropertyValue( PROPERTY_COMMAND_TYPE ) >>= _out_rCommandType );
703 
704     std::unique_ptr< ICopyTableSourceObject > pSourceObject;
705     Reference< XNameAccess > xContainer;
706     switch ( _out_rCommandType )
707     {
708     case CommandType::TABLE:
709     {
710         Reference< XTablesSupplier > xSuppTables( m_xSourceConnection.getTyped(), UNO_QUERY );
711         if ( xSuppTables.is() )
712             xContainer.set( xSuppTables->getTables(), UNO_SET_THROW );
713     }
714     break;
715     case CommandType::QUERY:
716     {
717         Reference< XQueriesSupplier > xSuppQueries( m_xSourceConnection.getTyped(), UNO_QUERY );
718         if ( xSuppQueries.is() )
719             xContainer.set( xSuppQueries->getQueries(), UNO_SET_THROW );
720     }
721     break;
722     default:
723         throw IllegalArgumentException(
724             DBA_RES( STR_CTW_ONLY_TABLES_AND_QUERIES_SUPPORT ),
725             *const_cast< CopyTableWizard* >( this ),
726             1
727         );
728     }
729 
730     if ( xContainer.is() )
731     {
732         pSourceObject.reset( new ObjectCopySource( m_xSourceConnection,
733             Reference< XPropertySet >( xContainer->getByName( sCommand ), UNO_QUERY_THROW ) ) );
734     }
735     else
736     {
737         // our source connection is an SDBC level connection only, not a SDBCX level one
738         // Which means it cannot provide the to-be-copied object as component.
739 
740         if ( _out_rCommandType == CommandType::QUERY )
741             // we cannot copy a query if the connection cannot provide it ...
742             throw IllegalArgumentException(
743                 DBA_RES( STR_CTW_ERROR_NO_QUERY ),
744                 *const_cast< CopyTableWizard* >( this ),
745                 1
746             );
747         pSourceObject.reset( new NamedTableCopySource( m_xSourceConnection, sCommand ) );
748     }
749 
750     return pSourceObject;
751 }
752 
impl_extractSourceResultSet_throw(const Reference<XPropertySet> & i_rDescriptor)753 void CopyTableWizard::impl_extractSourceResultSet_throw( const Reference< XPropertySet >& i_rDescriptor )
754 {
755     Reference< XPropertySetInfo > xPSI( i_rDescriptor->getPropertySetInfo(), UNO_SET_THROW );
756 
757     // extract relevant settings
758     if ( xPSI->hasPropertyByName( PROPERTY_RESULT_SET ) )
759         m_xSourceResultSet.set( i_rDescriptor->getPropertyValue( PROPERTY_RESULT_SET ), UNO_QUERY );
760 
761     if ( xPSI->hasPropertyByName( PROPERTY_SELECTION ) )
762         OSL_VERIFY( i_rDescriptor->getPropertyValue( PROPERTY_SELECTION ) >>= m_aSourceSelection );
763 
764     if ( xPSI->hasPropertyByName( PROPERTY_BOOKMARK_SELECTION ) )
765         OSL_VERIFY( i_rDescriptor->getPropertyValue( PROPERTY_BOOKMARK_SELECTION ) >>= m_bSourceSelectionBookmarks );
766 
767     // sanity checks
768     const bool bHasResultSet = m_xSourceResultSet.is();
769     const bool bHasSelection = m_aSourceSelection.hasElements();
770     if ( bHasSelection && !bHasResultSet )
771         throw IllegalArgumentException(u"A result set is needed when specifying a selection to copy."_ustr,
772                                        // TODO: resource
773                                        *this, 1);
774 
775     if ( bHasSelection && m_bSourceSelectionBookmarks )
776     {
777         Reference< XRowLocate > xRowLocate( m_xSourceResultSet, UNO_QUERY );
778         if ( !xRowLocate.is() )
779         {
780             ::dbtools::throwGenericSQLException(
781                 DBA_RES(STR_CTW_COPY_SOURCE_NEEDS_BOOKMARKS),
782                 *this
783             );
784         }
785     }
786 }
787 
impl_extractConnection_throw(const Reference<XPropertySet> & _rxDataSourceDescriptor,Reference<XInteractionHandler> & _out_rxDocInteractionHandler) const788 SharedConnection CopyTableWizard::impl_extractConnection_throw( const Reference< XPropertySet >& _rxDataSourceDescriptor,
789     Reference< XInteractionHandler >& _out_rxDocInteractionHandler ) const
790 {
791     SharedConnection xConnection;
792 
793     OSL_PRECOND( _rxDataSourceDescriptor.is(), "CopyTableWizard::impl_extractConnection_throw: no descriptor!" );
794     if ( !_rxDataSourceDescriptor.is() )
795         return xConnection;
796 
797     Reference< XInteractionHandler > xInteractionHandler;
798 
799     do
800     {
801         Reference< XPropertySetInfo > xPSI( _rxDataSourceDescriptor->getPropertySetInfo(), UNO_SET_THROW );
802 
803         // if there's an ActiveConnection, use it
804         if ( xPSI->hasPropertyByName( PROPERTY_ACTIVE_CONNECTION ) )
805         {
806             Reference< XConnection > xPure;
807             OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xPure );
808             xConnection.reset( xPure, SharedConnection::NoTakeOwnership );
809         }
810         if ( xConnection.is() )
811         {
812             xInteractionHandler = lcl_getInteractionHandler_throw( xConnection.getTyped(), m_xInteractionHandler );
813             SAL_WARN_IF( !xInteractionHandler.is(), "dbaccess.ui", "CopyTableWizard::impl_extractConnection_throw: lcl_getInteractionHandler_throw returned nonsense!" );
814             break;
815         }
816 
817         // there could be a DataSourceName or a DatabaseLocation, describing the css.sdb.DataSource
818         OUString sDataSource, sDatabaseLocation;
819         if ( xPSI->hasPropertyByName( PROPERTY_DATASOURCENAME ) )
820             OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_DATASOURCENAME ) >>= sDataSource );
821         if ( xPSI->hasPropertyByName( PROPERTY_DATABASE_LOCATION ) )
822             OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_DATABASE_LOCATION ) >>= sDatabaseLocation );
823 
824         // need a DatabaseContext for loading the data source
825         Reference< XDatabaseContext > xDatabaseContext = DatabaseContext::create( m_xContext );
826         Reference< XDataSource > xDataSource;
827         if ( !sDataSource.isEmpty() )
828             xDataSource.set( xDatabaseContext->getByName( sDataSource ), UNO_QUERY_THROW );
829         if ( !xDataSource.is() && !sDatabaseLocation.isEmpty() )
830             xDataSource.set( xDatabaseContext->getByName( sDatabaseLocation ), UNO_QUERY_THROW );
831 
832         if ( xDataSource.is() )
833         {
834             // first, try connecting with completion
835             xInteractionHandler = lcl_getInteractionHandler_throw( xDataSource, m_xInteractionHandler );
836             SAL_WARN_IF( !xInteractionHandler.is(), "dbaccess.ui", "CopyTableWizard::impl_extractConnection_throw: lcl_getInteractionHandler_throw returned nonsense!" );
837             if ( xInteractionHandler.is() )
838             {
839                 Reference< XCompletedConnection > xInteractiveConnection( xDataSource, UNO_QUERY );
840                 if ( xInteractiveConnection.is() )
841                     xConnection.reset( xInteractiveConnection->connectWithCompletion( xInteractionHandler ), SharedConnection::TakeOwnership );
842             }
843 
844             // interactively connecting was not successful or possible -> connect without interaction
845             if ( !xConnection.is() )
846             {
847                 xConnection.reset( xDataSource->getConnection( OUString(), OUString() ), SharedConnection::TakeOwnership );
848             }
849         }
850 
851         if ( xConnection.is() )
852             break;
853 
854         // finally, there could be a ConnectionResource/ConnectionInfo
855         OUString sConnectionResource;
856         Sequence< PropertyValue > aConnectionInfo;
857         if ( xPSI->hasPropertyByName( PROPERTY_CONNECTION_RESOURCE ) )
858             OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_CONNECTION_RESOURCE ) >>= sConnectionResource );
859         if ( xPSI->hasPropertyByName( PROPERTY_CONNECTION_INFO ) )
860             OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_CONNECTION_INFO ) >>= aConnectionInfo );
861 
862         Reference< XDriverManager > xDriverManager;
863         try {
864             xDriverManager.set( ConnectionPool::create( m_xContext ), UNO_QUERY_THROW );
865         } catch( const Exception& ) {  }
866         if ( !xDriverManager.is() )
867             // no connection pool installed
868             xDriverManager.set( DriverManager::create( m_xContext ), UNO_QUERY_THROW );
869 
870         if ( aConnectionInfo.hasElements() )
871             xConnection.set( xDriverManager->getConnectionWithInfo( sConnectionResource, aConnectionInfo ), UNO_SET_THROW );
872         else
873             xConnection.set( xDriverManager->getConnection( sConnectionResource ), UNO_SET_THROW );
874     }
875     while ( false );
876 
877     if ( xInteractionHandler != m_xInteractionHandler )
878         _out_rxDocInteractionHandler = std::move(xInteractionHandler);
879 
880     return xConnection;
881 }
882 
impl_createSourceStatement_throw() const883 ::utl::SharedUNOComponent< XPreparedStatement > CopyTableWizard::impl_createSourceStatement_throw() const
884 {
885     OSL_PRECOND( m_xSourceConnection.is(), "CopyTableWizard::impl_createSourceStatement_throw: illegal call!" );
886     if ( !m_xSourceConnection.is() )
887         throw RuntimeException( u"CopyTableWizard::impl_createSourceStatement_throw: illegal call!"_ustr, *const_cast< CopyTableWizard* >( this ));
888 
889     ::utl::SharedUNOComponent< XPreparedStatement > xStatement;
890     switch ( m_nCommandType )
891     {
892     case CommandType::TABLE:
893         xStatement.set( m_pSourceObject->getPreparedSelectStatement(), UNO_SET_THROW );
894         break;
895 
896     case CommandType::QUERY:
897     {
898         OUString sQueryCommand( m_pSourceObject->getSelectStatement() );
899         xStatement.set( m_pSourceObject->getPreparedSelectStatement(), UNO_SET_THROW );
900 
901         // check whether we have to fill in parameter values
902         // create and fill a composer
903 
904         Reference< XMultiServiceFactory > xFactory( m_xSourceConnection, UNO_QUERY );
905         ::utl::SharedUNOComponent< XSingleSelectQueryComposer > xComposer;
906         if ( xFactory.is() )
907             // note: connections below the sdb-level are allowed to not support the XMultiServiceFactory interface
908             xComposer.set( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY );
909 
910         if ( xComposer.is() )
911         {
912             xComposer->setQuery( sQueryCommand );
913 
914             Reference< XParameters > xStatementParams( xStatement, UNO_QUERY );
915             OSL_ENSURE( xStatementParams.is(), "CopyTableWizard::impl_createSourceStatement_throw: no access to the statement's parameters!" );
916                 // the statement should be a css.sdbc.PreparedStatement (this is what
917                 // we created), and a prepared statement is required to support XParameters
918             if ( xStatementParams.is() )
919             {
920                 OSL_ENSURE( m_xInteractionHandler.is(),
921                    "CopyTableWizard::impl_createSourceStatement_throw: no interaction handler for the parameters request!" );
922                 // we should always have an interaction handler - as last fallback, we create an own one in ::initialize
923 
924                 if ( m_xInteractionHandler.is() )
925                     ::dbtools::askForParameters( xComposer, xStatementParams, m_xSourceConnection, m_xInteractionHandler );
926             }
927         }
928     }
929     break;
930 
931     default:
932         // this should not have survived initialization phase
933         throw RuntimeException(u"No case matched, this should not have survived the initialization phase"_ustr, *const_cast< CopyTableWizard* >( this ));
934     }
935 
936     return xStatement;
937 }
938 
939 namespace
940 {
941     class ValueTransfer
942     {
943     public:
ValueTransfer(std::vector<sal_Int32> _rColTypes,const Reference<XRow> & _rxSource,const Reference<XParameters> & _rxDest)944         ValueTransfer( std::vector< sal_Int32 > _rColTypes,
945             const Reference< XRow >& _rxSource, const Reference< XParameters >& _rxDest )
946             :m_ColTypes( std::move(_rColTypes) )
947             ,m_xSource( _rxSource )
948             ,m_xDest( _rxDest )
949         {
950         }
951 
952     template< typename VALUE_TYPE >
transferValue(sal_Int32 _nSourcePos,sal_Int32 _nDestPos,VALUE_TYPE (SAL_CALL XRow::* _pGetter)(sal_Int32),void (SAL_CALL XParameters::* _pSetter)(sal_Int32,VALUE_TYPE))953     void transferValue( sal_Int32 _nSourcePos, sal_Int32 _nDestPos,
954         VALUE_TYPE ( SAL_CALL XRow::*_pGetter )( sal_Int32 ),
955         void (SAL_CALL XParameters::*_pSetter)( sal_Int32, VALUE_TYPE ) )
956     {
957         VALUE_TYPE value( (m_xSource.get()->*_pGetter)( _nSourcePos ) );
958         if ( m_xSource->wasNull() )
959             m_xDest->setNull( _nDestPos, m_ColTypes[ _nSourcePos ] );
960         else
961             (m_xDest.get()->*_pSetter)( _nDestPos, value );
962     }
963 
964     template< typename VALUE_TYPE >
transferComplexValue(sal_Int32 _nSourcePos,sal_Int32 _nDestPos,VALUE_TYPE (SAL_CALL XRow::* _pGetter)(sal_Int32),void (SAL_CALL XParameters::* _pSetter)(sal_Int32,const VALUE_TYPE &))965     void transferComplexValue( sal_Int32 _nSourcePos, sal_Int32 _nDestPos,
966         VALUE_TYPE ( SAL_CALL XRow::*_pGetter )( sal_Int32 ),
967         void (SAL_CALL XParameters::*_pSetter)( sal_Int32, const VALUE_TYPE& ) )
968     {
969         const VALUE_TYPE value( (m_xSource.get()->*_pGetter)( _nSourcePos ) );
970         if ( m_xSource->wasNull() )
971             m_xDest->setNull( _nDestPos, m_ColTypes[ _nSourcePos ] );
972         else
973             (m_xDest.get()->*_pSetter)( _nDestPos, value );
974     }
975     private:
976         const std::vector< sal_Int32 >      m_ColTypes;
977         const Reference< XRow >             m_xSource;
978         const Reference< XParameters >      m_xDest;
979     };
980 }
981 
impl_processCopyError_nothrow(const CopyTableRowEvent & _rEvent)982 bool CopyTableWizard::impl_processCopyError_nothrow( const CopyTableRowEvent& _rEvent )
983 {
984     try
985     {
986         ::comphelper::OInterfaceIteratorHelper3 aIter( m_aCopyTableListeners );
987         while ( aIter.hasMoreElements() )
988         {
989             Reference< XCopyTableListener > xListener( aIter.next() );
990             sal_Int16 nListenerChoice = xListener->copyRowError( _rEvent );
991             switch ( nListenerChoice )
992             {
993             case CopyTableContinuation::Proceed:            return true;    // continue copying
994             case CopyTableContinuation::CallNextHandler:    continue;       // continue the loop, ask next listener
995             case CopyTableContinuation::Cancel:             return false;   // cancel copying
996             case CopyTableContinuation::AskUser:            break;          // stop asking the listeners, ask the user
997 
998             default:
999                 SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_processCopyError_nothrow: invalid listener response!" );
1000                 // ask next listener
1001                 continue;
1002             }
1003         }
1004     }
1005     catch( const Exception& )
1006     {
1007         DBG_UNHANDLED_EXCEPTION("dbaccess");
1008     }
1009 
1010     // no listener felt responsible for the error, or a listener told to ask the user
1011 
1012     try
1013     {
1014         css::uno::Any next;
1015         ::dbtools::SQLExceptionInfo aInfo( _rEvent.Error );
1016         if ( aInfo.isValid() )
1017             next = _rEvent.Error;
1018         else
1019         {
1020             // a non-SQL exception happened
1021             Exception aException;
1022             OSL_VERIFY( _rEvent.Error >>= aException );
1023             SQLContext aContext(aException.Message, aException.Context, {}, 0, {},
1024                                 _rEvent.Error.getValueTypeName());
1025             next <<= aContext;
1026         }
1027         SQLContext aError(DBA_RES(STR_ERROR_OCCURRED_WHILE_COPYING), *this, {}, 0, next, {});
1028 
1029         ::rtl::Reference< ::comphelper::OInteractionRequest > xRequest( new ::comphelper::OInteractionRequest( Any( aError ) ) );
1030 
1031         ::rtl::Reference< ::comphelper::OInteractionApprove > xYes = new ::comphelper::OInteractionApprove;
1032         xRequest->addContinuation( xYes );
1033         xRequest->addContinuation( new ::comphelper::OInteractionDisapprove );
1034 
1035         OSL_ENSURE( m_xInteractionHandler.is(),
1036             "CopyTableWizard::impl_processCopyError_nothrow: we always should have an interaction handler!" );
1037         if ( m_xInteractionHandler.is() )
1038             m_xInteractionHandler->handle( xRequest );
1039 
1040         if ( xYes->wasSelected() )
1041             // continue copying
1042             return true;
1043     }
1044     catch( const Exception& )
1045     {
1046         DBG_UNHANDLED_EXCEPTION("dbaccess");
1047     }
1048 
1049     // cancel copying
1050     return false;
1051 }
1052 
impl_copyRows_throw(const Reference<XResultSet> & _rxSourceResultSet,const Reference<XPropertySet> & _rxDestTable)1053 void CopyTableWizard::impl_copyRows_throw( const Reference< XResultSet >& _rxSourceResultSet,
1054     const Reference< XPropertySet >& _rxDestTable )
1055 {
1056     OSL_PRECOND( m_xDestConnection.is(), "CopyTableWizard::impl_copyRows_throw: illegal call!" );
1057     if ( !m_xDestConnection.is() )
1058         throw RuntimeException( u"m_xDestConnection is set to null, CopyTableWizard::impl_copyRows_throw: illegal call!"_ustr, *this );
1059 
1060     Reference< XDatabaseMetaData > xDestMetaData( m_xDestConnection->getMetaData(), UNO_SET_THROW );
1061 
1062     const OCopyTableWizard& rWizard             = impl_getDialog_throw();
1063     ODatabaseExport::TPositions aColumnPositions = rWizard.GetColumnPositions();
1064     const bool bShouldCreatePrimaryKey = rWizard.shouldCreatePrimaryKey();
1065 
1066     Reference< XRow > xRow              ( _rxSourceResultSet, UNO_QUERY_THROW );
1067     Reference< XRowLocate > xRowLocate  ( _rxSourceResultSet, UNO_QUERY_THROW );
1068 
1069     Reference< XResultSetMetaDataSupplier > xSuppResMeta( _rxSourceResultSet, UNO_QUERY_THROW );
1070     Reference< XResultSetMetaData> xMeta( xSuppResMeta->getMetaData() );
1071 
1072     // we need a vector which all types
1073     sal_Int32 nCount = xMeta->getColumnCount();
1074     std::vector< sal_Int32 > aSourceColTypes;
1075     aSourceColTypes.reserve( nCount + 1 );
1076     aSourceColTypes.push_back( -1 ); // just to avoid an every time i-1 call
1077 
1078     std::vector< sal_Int32 > aSourcePrec;
1079     aSourcePrec.reserve( nCount + 1 );
1080     aSourcePrec.push_back( -1 ); // just to avoid an every time i-1 call
1081 
1082     for ( sal_Int32 k=1; k <= nCount; ++k )
1083     {
1084         aSourceColTypes.push_back( xMeta->getColumnType( k ) );
1085         aSourcePrec.push_back( xMeta->getPrecision( k ) );
1086     }
1087 
1088     // now create, fill and execute the prepared statement
1089     Reference< XPreparedStatement > xStatement( ODatabaseExport::createPreparedStatement( xDestMetaData, _rxDestTable, aColumnPositions ), UNO_SET_THROW );
1090     Reference< XParameters > xStatementParams( xStatement, UNO_QUERY_THROW );
1091 
1092     const bool bSelectedRecordsOnly = m_aSourceSelection.hasElements();
1093     const Any* pSelectedRow         = m_aSourceSelection.begin();
1094     const Any* pSelEnd              = m_aSourceSelection.end();
1095 
1096     sal_Int32 nRowCount = 0;
1097     bool bContinue = false;
1098 
1099     CopyTableRowEvent aCopyEvent;
1100     aCopyEvent.Source = *this;
1101     aCopyEvent.SourceData = _rxSourceResultSet;
1102 
1103     do // loop as long as there are more rows or the selection ends
1104     {
1105         bContinue = false;
1106         if ( bSelectedRecordsOnly )
1107         {
1108             if ( pSelectedRow != pSelEnd )
1109             {
1110                 if ( m_bSourceSelectionBookmarks )
1111                 {
1112                     bContinue = xRowLocate->moveToBookmark( *pSelectedRow );
1113                 }
1114                 else
1115                 {
1116                     sal_Int32 nPos = 0;
1117                     OSL_VERIFY( *pSelectedRow >>= nPos );
1118                     bContinue = _rxSourceResultSet->absolute( nPos );
1119                 }
1120                 ++pSelectedRow;
1121             }
1122         }
1123         else
1124             bContinue = _rxSourceResultSet->next();
1125 
1126         if ( !bContinue )
1127         {
1128             break;
1129         }
1130 
1131         ++nRowCount;
1132 
1133         aCopyEvent.Error.clear();
1134         try
1135         {
1136             bool bInsertedPrimaryKey = false;
1137             // notify listeners
1138             m_aCopyTableListeners.notifyEach( &XCopyTableListener::copyingRow, aCopyEvent );
1139 
1140             sal_Int32 nSourceColumn( 1 );
1141             ValueTransfer aTransfer( aSourceColTypes, xRow, xStatementParams );
1142 
1143             for ( auto const& rColumnPos : aColumnPositions )
1144             {
1145                 sal_Int32 nDestColumn = rColumnPos.first;
1146                 if ( nDestColumn == COLUMN_POSITION_NOT_FOUND )
1147                 {
1148                     ++nSourceColumn;
1149                     // otherwise we don't get the correct value when only the 2nd source column was selected
1150                     continue;
1151                 }
1152 
1153                 if ( bShouldCreatePrimaryKey && !bInsertedPrimaryKey )
1154                 {
1155                     xStatementParams->setInt( 1, nRowCount );
1156                     ++nSourceColumn;
1157                     bInsertedPrimaryKey = true;
1158                     continue;
1159                 }
1160 
1161                 if ( ( nSourceColumn < 1 ) || ( o3tl::make_unsigned(nSourceColumn) >= aSourceColTypes.size() ) )
1162                 {   // ( we have to check here against 1 because the parameters are 1 based)
1163                     ::dbtools::throwSQLException(u"Internal error: invalid column type index."_ustr,
1164                                                  ::dbtools::StandardSQLState::INVALID_DESCRIPTOR_INDEX, *this);
1165                 }
1166 
1167                 switch ( aSourceColTypes[ nSourceColumn ] )
1168                 {
1169                     case DataType::DOUBLE:
1170                     case DataType::REAL:
1171                         aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getDouble, &XParameters::setDouble );
1172                         break;
1173 
1174                     case DataType::CHAR:
1175                     case DataType::VARCHAR:
1176                     case DataType::LONGVARCHAR:
1177                     case DataType::DECIMAL:
1178                     case DataType::NUMERIC:
1179                         aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getString, &XParameters::setString );
1180                         break;
1181 
1182                     case DataType::BIGINT:
1183                         aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getLong, &XParameters::setLong );
1184                         break;
1185 
1186                     case DataType::FLOAT:
1187                         aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getFloat, &XParameters::setFloat );
1188                         break;
1189 
1190                     case DataType::LONGVARBINARY:
1191                     case DataType::BINARY:
1192                     case DataType::VARBINARY:
1193                         aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getBytes, &XParameters::setBytes );
1194                         break;
1195 
1196                     case DataType::DATE:
1197                         aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getDate, &XParameters::setDate );
1198                         break;
1199 
1200                     case DataType::TIME:
1201                         aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getTime, &XParameters::setTime );
1202                         break;
1203 
1204                     case DataType::TIMESTAMP:
1205                         aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getTimestamp, &XParameters::setTimestamp );
1206                         break;
1207 
1208                     case DataType::BIT:
1209                         if ( aSourcePrec[nSourceColumn] > 1 )
1210                         {
1211                             aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getBytes, &XParameters::setBytes );
1212                             break;
1213                         }
1214                         [[fallthrough]];
1215                     case DataType::BOOLEAN:
1216                         aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getBoolean, &XParameters::setBoolean );
1217                         break;
1218 
1219                     case DataType::TINYINT:
1220                         aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getByte, &XParameters::setByte );
1221                         break;
1222 
1223                     case DataType::SMALLINT:
1224                         aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getShort, &XParameters::setShort );
1225                         break;
1226 
1227                     case DataType::INTEGER:
1228                         aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getInt, &XParameters::setInt );
1229                         break;
1230 
1231                     case DataType::BLOB:
1232                         aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getBlob, &XParameters::setBlob );
1233                         break;
1234 
1235                     case DataType::CLOB:
1236                         aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getClob, &XParameters::setClob );
1237                         break;
1238 
1239                     default:
1240                     {
1241                         OUString aMessage( DBA_RES( STR_CTW_UNSUPPORTED_COLUMN_TYPE ) );
1242 
1243                         aMessage = aMessage.replaceFirst( "$type$", OUString::number( aSourceColTypes[ nSourceColumn ] ) );
1244                         aMessage = aMessage.replaceFirst( "$pos$", OUString::number( nSourceColumn ) );
1245 
1246                         ::dbtools::throwSQLException(
1247                             aMessage,
1248                             ::dbtools::StandardSQLState::INVALID_SQL_DATA_TYPE,
1249                             *this
1250                         );
1251                     }
1252                 }
1253                 ++nSourceColumn;
1254             }
1255             xStatement->executeUpdate();
1256 
1257             // notify listeners
1258             m_aCopyTableListeners.notifyEach( &XCopyTableListener::copiedRow, aCopyEvent );
1259         }
1260         catch( const Exception& )
1261         {
1262             TOOLS_WARN_EXCEPTION("dbaccess", "");
1263             aCopyEvent.Error = ::cppu::getCaughtException();
1264         }
1265 
1266         if ( aCopyEvent.Error.hasValue() )
1267             bContinue = impl_processCopyError_nothrow( aCopyEvent );
1268     }
1269     while( bContinue );
1270 }
1271 
impl_doCopy_nothrow()1272 void CopyTableWizard::impl_doCopy_nothrow()
1273 {
1274     Any aError;
1275 
1276     try
1277     {
1278         OCopyTableWizard& rWizard( impl_getDialog_throw() );
1279 
1280         weld::WaitObject aWO(rWizard.getDialog());
1281         Reference< XPropertySet > xTable;
1282 
1283         switch ( rWizard.getOperation() )
1284         {
1285             case CopyTableOperation::CopyDefinitionOnly:
1286             case CopyTableOperation::CopyDefinitionAndData:
1287             {
1288                 xTable = rWizard.createTable();
1289 
1290                 if( !xTable.is() )
1291                 {
1292                     SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_doCopy_nothrow: createTable should throw here, shouldn't it?" );
1293                     break;
1294                 }
1295 
1296                 if( CopyTableOperation::CopyDefinitionOnly == rWizard.getOperation() )
1297                     break;
1298 
1299                 [[fallthrough]];
1300             }
1301 
1302             case CopyTableOperation::AppendData:
1303             {
1304                 // note that the CopyDefinitionAndData case falls through to here.
1305                 assert((rWizard.getOperation() == CopyTableOperation::CopyDefinitionAndData) ||
1306                        (rWizard.getOperation() == CopyTableOperation::AppendData));
1307                 assert((rWizard.getOperation() == CopyTableOperation::CopyDefinitionAndData) == xTable.is());
1308                 if ( !xTable.is() )
1309                 {
1310                     assert(rWizard.getOperation() == CopyTableOperation::AppendData);
1311                     xTable = rWizard.getTable();
1312                     if ( !xTable.is() )
1313                     {
1314                         SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_doCopy_nothrow: getTable should throw here, shouldn't it?" );
1315                         break;
1316                     }
1317                 }
1318 
1319                 ::utl::SharedUNOComponent< XPreparedStatement > xSourceStatement;
1320                 ::utl::SharedUNOComponent< XResultSet > xSourceResultSet;
1321 
1322                 if ( m_xSourceResultSet.is() )
1323                 {
1324                     xSourceResultSet.reset( m_xSourceResultSet, ::utl::SharedUNOComponent< XResultSet >::NoTakeOwnership );
1325                 }
1326                 else
1327                 {
1328                     const bool bIsSameConnection = ( m_xSourceConnection.getTyped() == m_xDestConnection.getTyped() );
1329                     const bool bIsTable = ( CommandType::TABLE == m_nCommandType );
1330                     bool bDone = false;
1331                     if ( bIsSameConnection && bIsTable )
1332                     {
1333                         // try whether the server supports copying via SQL
1334                         try
1335                         {
1336                             m_xDestConnection->createStatement()->executeUpdate( impl_getServerSideCopyStatement_throw(xTable) );
1337                             bDone = true;
1338                         }
1339                         catch( const Exception& )
1340                         {
1341                             // this is allowed.
1342                         }
1343                     }
1344 
1345                     if ( !bDone )
1346                     {
1347                         xSourceStatement.set( impl_createSourceStatement_throw(), UNO_SET_THROW );
1348                         xSourceResultSet.set( xSourceStatement->executeQuery(), UNO_SET_THROW );
1349                     }
1350                 }
1351 
1352                 if ( xSourceResultSet.is() )
1353                     impl_copyRows_throw( xSourceResultSet, xTable );
1354 
1355                 // tdf#119962
1356                 const Reference< XDatabaseMetaData > xDestMetaData( m_xDestConnection->getMetaData(), UNO_SET_THROW );
1357                 OUString sDatabaseDest = xDestMetaData->getDatabaseProductName().toAsciiLowerCase();
1358                 // If we created a new primary key, then it won't necessarily be an IDENTITY column
1359                 const bool bShouldCreatePrimaryKey = rWizard.shouldCreatePrimaryKey();
1360                 if ( !bShouldCreatePrimaryKey && (sDatabaseDest.indexOf("firebird") != -1) )
1361                 {
1362                     const OUString sComposedTableName = ::dbtools::composeTableName( xDestMetaData, xTable, ::dbtools::EComposeRule::InDataManipulation, true );
1363 
1364                     OUString aSchema,aTable;
1365                     xTable->getPropertyValue(u"SchemaName"_ustr) >>= aSchema;
1366                     xTable->getPropertyValue(u"Name"_ustr)       >>= aTable;
1367                     Any aCatalog = xTable->getPropertyValue(u"CatalogName"_ustr);
1368 
1369                     const Reference< XResultSet > xResultPKCL(xDestMetaData->getPrimaryKeys(aCatalog,aSchema,aTable));
1370                     Reference< XRow > xRowPKCL(xResultPKCL, UNO_QUERY_THROW);
1371                     OUString sPKCL;
1372                     if ( xRowPKCL.is() )
1373                     {
1374                         if (xResultPKCL->next())
1375                         {
1376                             sPKCL = xRowPKCL->getString(4);
1377                         }
1378                     }
1379 
1380                     if (!sPKCL.isEmpty())
1381                     {
1382                         OUString strSql = "SELECT MAX(\"" + sPKCL + "\") FROM " + sComposedTableName;
1383 
1384                         Reference< XResultSet > xResultMAXNUM(m_xDestConnection->createStatement()->executeQuery(strSql));
1385                         Reference< XRow > xRow(xResultMAXNUM, UNO_QUERY_THROW);
1386 
1387                         sal_Int64 maxVal = -1L;
1388                         if (xResultMAXNUM->next())
1389                         {
1390                             maxVal = xRow->getLong(1);
1391                         }
1392 
1393                         if (maxVal > 0L)
1394                         {
1395                             strSql = "ALTER TABLE " + sComposedTableName + " ALTER \"" + sPKCL + "\" RESTART WITH " + OUString::number(maxVal + 1);
1396 
1397                             m_xDestConnection->createStatement()->execute(strSql);
1398                         }
1399                     }
1400                 }
1401             }
1402             break;
1403 
1404             case CopyTableOperation::CreateAsView:
1405                 rWizard.createView();
1406                 break;
1407 
1408             default:
1409                 SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_doCopy_nothrow: What operation, please?" );
1410                 break;
1411         }
1412     }
1413     catch( const Exception& )
1414     {
1415         aError = ::cppu::getCaughtException();
1416         SAL_WARN("dbaccess", exceptionToString(aError));
1417 
1418         // silence the error of the user cancelling the parameter's dialog
1419         SQLException aSQLError;
1420         if ( ( aError >>= aSQLError ) && ( aSQLError.ErrorCode == ::dbtools::ParameterInteractionCancelled ) )
1421         {
1422             aError.clear();
1423             m_nOverrideExecutionResult = RET_CANCEL;
1424         }
1425     }
1426 
1427     if ( aError.hasValue() && m_xInteractionHandler.is() )
1428     {
1429         try
1430         {
1431             ::rtl::Reference< ::comphelper::OInteractionRequest > xRequest( new ::comphelper::OInteractionRequest( aError ) );
1432             m_xInteractionHandler->handle( xRequest );
1433         }
1434         catch( const Exception& )
1435         {
1436             DBG_UNHANDLED_EXCEPTION("dbaccess");
1437         }
1438     }
1439 }
1440 
impl_getServerSideCopyStatement_throw(const Reference<XPropertySet> & _xTable)1441 OUString CopyTableWizard::impl_getServerSideCopyStatement_throw(const Reference< XPropertySet >& _xTable)
1442 {
1443     const Reference<XColumnsSupplier> xDestColsSup(_xTable,UNO_QUERY_THROW);
1444     const Sequence< OUString> aDestColumnNames = xDestColsSup->getColumns()->getElementNames();
1445     const Reference< XDatabaseMetaData > xDestMetaData( m_xDestConnection->getMetaData(), UNO_SET_THROW );
1446     const OUString sQuote = xDestMetaData->getIdentifierQuoteString();
1447     OUStringBuffer sColumns;
1448     // 1st check if the columns matching
1449     for ( auto const & rColumnPositionPair : impl_getDialog_throw().GetColumnPositions() )
1450     {
1451         if ( COLUMN_POSITION_NOT_FOUND != rColumnPositionPair.second )
1452         {
1453             if ( !sColumns.isEmpty() )
1454                 sColumns.append(",");
1455             sColumns.append(sQuote + aDestColumnNames[rColumnPositionPair.second - 1] + sQuote);
1456         }
1457     }
1458     const OUString sComposedTableName = ::dbtools::composeTableName( xDestMetaData, _xTable, ::dbtools::EComposeRule::InDataManipulation, true );
1459     OUString sSql("INSERT INTO " + sComposedTableName + " ( " + sColumns + " ) " + m_pSourceObject->getSelectStatement());
1460 
1461     return sSql;
1462 }
1463 
initialize(const Sequence<Any> & _rArguments)1464 void SAL_CALL CopyTableWizard::initialize( const Sequence< Any >& _rArguments )
1465 {
1466     ::osl::MutexGuard aGuard( m_aMutex );
1467     if ( isInitialized() )
1468         throw AlreadyInitializedException( OUString(), *this );
1469 
1470     sal_Int32 nArgCount( _rArguments.getLength() );
1471     if ( ( nArgCount != 2 ) && ( nArgCount != 3 ) )
1472         throw IllegalArgumentException(
1473             DBA_RES( STR_CTW_ILLEGAL_PARAMETER_COUNT ),
1474             *this,
1475             1
1476         );
1477 
1478     try
1479     {
1480         if ( nArgCount == 3 )
1481         {   // ->createWithInteractionHandler
1482             if ( !( _rArguments[2] >>= m_xInteractionHandler ) )
1483                 throw IllegalArgumentException(
1484                     DBA_RES( STR_CTW_ERROR_INVALID_INTERACTIONHANDLER ),
1485                     *this,
1486                     3
1487                 );
1488         }
1489         if ( !m_xInteractionHandler.is() )
1490             m_xInteractionHandler = InteractionHandler::createWithParent(m_xContext, nullptr);
1491 
1492         Reference< XInteractionHandler > xSourceDocHandler;
1493         Reference< XPropertySet > xSourceDescriptor( impl_ensureDataAccessDescriptor_throw( _rArguments, 0, m_xSourceConnection, xSourceDocHandler ) );
1494         impl_checkForUnsupportedSettings_throw( xSourceDescriptor );
1495         m_pSourceObject = impl_extractSourceObject_throw( xSourceDescriptor, m_nCommandType );
1496         impl_extractSourceResultSet_throw( xSourceDescriptor );
1497 
1498         Reference< XInteractionHandler > xDestDocHandler;
1499         impl_ensureDataAccessDescriptor_throw( _rArguments, 1, m_xDestConnection, xDestDocHandler );
1500 
1501         if ( xDestDocHandler.is() && !m_xInteractionHandler.is() )
1502             m_xInteractionHandler = std::move(xDestDocHandler);
1503 
1504         Reference< XPropertySet > xInteractionHandler(m_xInteractionHandler, UNO_QUERY);
1505         if (xInteractionHandler.is())
1506         {
1507             Any aParentWindow(xInteractionHandler->getPropertyValue(u"ParentWindow"_ustr));
1508             aParentWindow >>= m_xParent;
1509         }
1510     }
1511     catch( const RuntimeException& ) { throw; }
1512     catch( const SQLException& ) { throw; }
1513     catch( const Exception& )
1514     {
1515         throw WrappedTargetException(
1516             DBA_RES( STR_CTW_ERROR_DURING_INITIALIZATION ),
1517             *this,
1518             ::cppu::getCaughtException()
1519         );
1520     }
1521 }
1522 
getInfoHelper()1523 ::cppu::IPropertyArrayHelper& CopyTableWizard::getInfoHelper()
1524 {
1525     return *getArrayHelper();
1526 }
1527 
createArrayHelper() const1528 ::cppu::IPropertyArrayHelper* CopyTableWizard::createArrayHelper( ) const
1529 {
1530     Sequence< Property > aProps;
1531     describeProperties( aProps );
1532     return new ::cppu::OPropertyArrayHelper( aProps );
1533 }
1534 
createDialog(const css::uno::Reference<css::awt::XWindow> & rParent)1535 std::unique_ptr<weld::DialogController> CopyTableWizard::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
1536 {
1537     OSL_PRECOND( isInitialized(), "CopyTableWizard::createDialog: not initialized!" );
1538         // this should have been prevented in ::execute already
1539 
1540     auto xWizard = std::make_unique<OCopyTableWizard>(
1541         Application::GetFrameWeld(rParent),
1542         m_sDestinationTable,
1543         m_nOperation,
1544         *m_pSourceObject,
1545         m_xSourceConnection.getTyped(),
1546         m_xDestConnection.getTyped(),
1547         m_xContext,
1548         m_xInteractionHandler);
1549 
1550     impl_attributesToDialog_nothrow(*xWizard);
1551 
1552     return xWizard;
1553 }
1554 
executedDialog(sal_Int16 _nExecutionResult)1555 void CopyTableWizard::executedDialog( sal_Int16 _nExecutionResult )
1556 {
1557     CopyTableWizard_DialogBase::executedDialog( _nExecutionResult );
1558 
1559     if ( _nExecutionResult == RET_OK )
1560         impl_doCopy_nothrow();
1561 
1562     // do this after impl_doCopy_nothrow: The attributes may change during copying, for instance
1563     // if the user entered an unqualified table name
1564     impl_dialogToAttributes_nothrow( impl_getDialog_throw() );
1565 }
1566 
1567 } // namespace dbaui
1568 
1569 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
org_openoffice_comp_dbu_CopyTableWizard_get_implementation(css::uno::XComponentContext * context,css::uno::Sequence<css::uno::Any> const &)1570 org_openoffice_comp_dbu_CopyTableWizard_get_implementation(
1571     css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
1572 {
1573     return cppu::acquire(new ::dbaui::CopyTableWizard(context));
1574 }
1575 
1576 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1577