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