fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / dbaccess / source / ui / uno / copytablewizard.cxx
blobbf5a00634914cf456d0fe540b3ad283c4bb95725
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "dbu_reghelper.hxx"
21 #include "dbu_resource.hrc"
22 #include "dbu_uno.hrc"
23 #include "dbustrings.hrc"
24 #include "moduledbu.hxx"
25 #include "sqlmessage.hxx"
26 #include "uiservices.hxx"
27 #include "WCopyTable.hxx"
29 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
30 #include <com/sun/star/sdb/application/XCopyTableWizard.hpp>
31 #include <com/sun/star/sdb/application/CopyTableContinuation.hpp>
32 #include <com/sun/star/sdb/application/CopyTableOperation.hpp>
33 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
34 #include <com/sun/star/lang/NotInitializedException.hpp>
35 #include <com/sun/star/sdbc/XDataSource.hpp>
36 #include <com/sun/star/sdbc/DataType.hpp>
37 #include <com/sun/star/container/XNameAccess.hpp>
38 #include <com/sun/star/container/XChild.hpp>
39 #include <com/sun/star/task/InteractionHandler.hpp>
40 #include <com/sun/star/frame/XModel.hpp>
41 #include <com/sun/star/sdb/DatabaseContext.hpp>
42 #include <com/sun/star/sdb/XDocumentDataSource.hpp>
43 #include <com/sun/star/sdb/XCompletedConnection.hpp>
44 #include <com/sun/star/sdb/CommandType.hpp>
45 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
46 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
47 #include <com/sun/star/lang/DisposedException.hpp>
48 #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
49 #include <com/sun/star/sdbc/XParameters.hpp>
50 #include <com/sun/star/sdbc/XRow.hpp>
51 #include <com/sun/star/sdbc/XBlob.hpp>
52 #include <com/sun/star/sdbc/XClob.hpp>
53 #include <com/sun/star/sdbcx/XRowLocate.hpp>
54 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
55 #include <com/sun/star/sdb/SQLContext.hpp>
56 #include <com/sun/star/sdbc/DriverManager.hpp>
57 #include <com/sun/star/sdbc/ConnectionPool.hpp>
59 #include <comphelper/processfactory.hxx>
60 #include <comphelper/interaction.hxx>
61 #include <comphelper/namedvaluecollection.hxx>
62 #include <comphelper/proparrhlp.hxx>
63 #include <connectivity/dbexception.hxx>
64 #include <connectivity/dbtools.hxx>
65 #include <cppuhelper/exc_hlp.hxx>
66 #include <cppuhelper/implbase1.hxx>
67 #include <rtl/ustrbuf.hxx>
68 #include <svtools/genericunodialog.hxx>
69 #include <tools/diagnose_ex.h>
70 #include <unotools/sharedunocomponent.hxx>
71 #include <vcl/msgbox.hxx>
72 #include <vcl/waitobj.hxx>
74 namespace dbaui
77 using ::com::sun::star::uno::Reference;
78 using ::com::sun::star::uno::XInterface;
79 using ::com::sun::star::uno::UNO_QUERY;
80 using ::com::sun::star::uno::UNO_QUERY_THROW;
81 using ::com::sun::star::uno::UNO_SET_THROW;
82 using ::com::sun::star::uno::Exception;
83 using ::com::sun::star::uno::RuntimeException;
84 using ::com::sun::star::uno::Any;
85 using ::com::sun::star::uno::makeAny;
86 using ::com::sun::star::uno::Sequence;
87 using ::com::sun::star::uno::XComponentContext;
88 using ::com::sun::star::beans::XPropertySetInfo;
89 using ::com::sun::star::lang::XMultiServiceFactory;
90 using ::com::sun::star::beans::Property;
91 using ::com::sun::star::sdb::application::XCopyTableWizard;
92 using ::com::sun::star::sdb::application::XCopyTableListener;
93 using ::com::sun::star::sdb::application::CopyTableRowEvent;
94 using ::com::sun::star::beans::Optional;
95 using ::com::sun::star::lang::IllegalArgumentException;
96 using ::com::sun::star::ucb::AlreadyInitializedException;
97 using ::com::sun::star::beans::XPropertySet;
98 using ::com::sun::star::lang::NotInitializedException;
99 using ::com::sun::star::lang::XServiceInfo;
100 using ::com::sun::star::sdbc::XConnection;
101 using ::com::sun::star::sdbc::XDataSource;
102 using ::com::sun::star::container::XNameAccess;
103 using ::com::sun::star::container::XChild;
104 using ::com::sun::star::task::InteractionHandler;
105 using ::com::sun::star::task::XInteractionHandler;
106 using ::com::sun::star::frame::XModel;
107 using ::com::sun::star::sdb::DatabaseContext;
108 using ::com::sun::star::sdb::XDatabaseContext;
109 using ::com::sun::star::sdb::XDocumentDataSource;
110 using ::com::sun::star::sdb::XCompletedConnection;
111 using ::com::sun::star::lang::WrappedTargetException;
112 using ::com::sun::star::sdbcx::XTablesSupplier;
113 using ::com::sun::star::sdb::XQueriesSupplier;
114 using ::com::sun::star::lang::DisposedException;
115 using ::com::sun::star::sdbc::XPreparedStatement;
116 using ::com::sun::star::sdb::XSingleSelectQueryComposer;
117 using ::com::sun::star::sdbc::XDatabaseMetaData;
118 using ::com::sun::star::sdbcx::XColumnsSupplier;
119 using ::com::sun::star::sdbc::XParameters;
120 using ::com::sun::star::sdbc::XResultSet;
121 using ::com::sun::star::sdbc::XRow;
122 using ::com::sun::star::sdbc::XBlob;
123 using ::com::sun::star::sdbc::XClob;
124 using ::com::sun::star::sdbcx::XRowLocate;
125 using ::com::sun::star::sdbc::XResultSetMetaDataSupplier;
126 using ::com::sun::star::sdbc::XResultSetMetaData;
127 using ::com::sun::star::sdbc::SQLException;
128 using ::com::sun::star::sdb::SQLContext;
129 using ::com::sun::star::sdbc::ConnectionPool;
130 using ::com::sun::star::sdbc::XConnectionPool;
131 using ::com::sun::star::sdbc::XDriverManager;
132 using ::com::sun::star::sdbc::DriverManager;
133 using ::com::sun::star::beans::PropertyValue;
135 namespace CopyTableOperation = ::com::sun::star::sdb::application::CopyTableOperation;
136 namespace CopyTableContinuation = ::com::sun::star::sdb::application::CopyTableContinuation;
137 namespace CommandType = ::com::sun::star::sdb::CommandType;
138 namespace DataType = ::com::sun::star::sdbc::DataType;
140 typedef ::utl::SharedUNOComponent< XConnection > SharedConnection;
142 // CopyTableWizard
143 typedef ::svt::OGenericUnoDialog CopyTableWizard_DialogBase;
144 typedef ::cppu::ImplInheritanceHelper1 < CopyTableWizard_DialogBase
145 , XCopyTableWizard
146 > CopyTableWizard_Base;
147 class CopyTableWizard
148 :public CopyTableWizard_Base
149 ,public ::comphelper::OPropertyArrayUsageHelper< CopyTableWizard >
151 public:
152 // XServiceInfo
153 virtual OUString SAL_CALL getImplementationName() throw(RuntimeException, std::exception) SAL_OVERRIDE;
154 virtual ::comphelper::StringSequence SAL_CALL getSupportedServiceNames() throw(RuntimeException, std::exception) SAL_OVERRIDE;
156 // XServiceInfo - static methods
157 static Sequence< OUString > getSupportedServiceNames_Static() throw( RuntimeException );
158 static OUString getImplementationName_Static() throw( RuntimeException );
159 static Reference< XInterface > Create( const Reference< XMultiServiceFactory >& );
161 // XCopyTableWizard
162 virtual ::sal_Int16 SAL_CALL getOperation() throw (RuntimeException, std::exception) SAL_OVERRIDE;
163 virtual void SAL_CALL setOperation( ::sal_Int16 _operation ) throw (IllegalArgumentException, RuntimeException, std::exception) SAL_OVERRIDE;
164 virtual OUString SAL_CALL getDestinationTableName() throw (RuntimeException, std::exception) SAL_OVERRIDE;
165 virtual void SAL_CALL setDestinationTableName( const OUString& _destinationTableName ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
166 virtual Optional< OUString > SAL_CALL getCreatePrimaryKey() throw (RuntimeException, std::exception) SAL_OVERRIDE;
167 virtual void SAL_CALL setCreatePrimaryKey( const Optional< OUString >& _newPrimaryKey ) throw (IllegalArgumentException, SQLException, RuntimeException, std::exception) SAL_OVERRIDE;
168 virtual sal_Bool SAL_CALL getUseHeaderLineAsColumnNames() throw (RuntimeException, std::exception) SAL_OVERRIDE;
169 virtual void SAL_CALL setUseHeaderLineAsColumnNames( sal_Bool _bUseHeaderLineAsColumnNames ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
170 virtual void SAL_CALL addCopyTableListener( const Reference< XCopyTableListener >& Listener ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
171 virtual void SAL_CALL removeCopyTableListener( const Reference< XCopyTableListener >& Listener ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
173 // XCopyTableWizard::XExecutableDialog
174 virtual void SAL_CALL setTitle( const OUString& aTitle ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
175 virtual ::sal_Int16 SAL_CALL execute( ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
177 // XInitialization
178 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException, std::exception) SAL_OVERRIDE;
180 // XPropertySet
181 virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo() throw(RuntimeException, std::exception) SAL_OVERRIDE;
182 virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() SAL_OVERRIDE;
184 // OPropertyArrayUsageHelper
185 virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const SAL_OVERRIDE;
187 public:
188 ::osl::Mutex& getMutex() { return m_aMutex; }
189 bool isInitialized() const { return m_xSourceConnection.is() && m_pSourceObject.get() && m_xDestConnection.is(); }
191 protected:
192 CopyTableWizard( const Reference< XComponentContext >& _rxORB );
193 virtual ~CopyTableWizard();
195 // OGenericUnoDialog overridables
196 virtual VclPtr<Dialog> createDialog( vcl::Window* _pParent ) SAL_OVERRIDE;
197 virtual void executedDialog( sal_Int16 _nExecutionResult ) SAL_OVERRIDE;
199 private:
200 /// ensures our current attribute values are reflected in the dialog
201 void impl_attributesToDialog_nothrow( OCopyTableWizard& _rDialog ) const;
203 /// ensures the current dialog settings are reflected in our attributes
204 void impl_dialogToAttributes_nothrow( const OCopyTableWizard& _rDialog );
206 /** returns our typed dialog
208 @throws ::com::sun::star::uno::RuntimeException
209 if we don't have a dialog at the moment the method is called
211 OCopyTableWizard&
212 impl_getDialog_throw();
214 /** ensures the given argument sequence contains a valid data access descriptor at the given position
215 @param _rAllArgs
216 the arguments as passed to ->initialize
217 @param _nArgPos
218 the position within ->_rAllArgs which contains the data access descriptor
219 @param _out_rxConnection
220 will, upon successful return, contain the connection for the data source
221 @param _out_rxDocInteractionHandler
222 will, upon successful return, contain the interaction handler which could
223 be deduced from database document described by the descriptor, if any.
224 (It is possible that the descriptor does not allow to deduce a database document,
225 in which case <code>_out_rxDocInteractionHandler</code> will be <NULL/>.)
226 @return the data access descriptor
228 Reference< XPropertySet >
229 impl_ensureDataAccessDescriptor_throw(
230 const Sequence< Any >& _rAllArgs,
231 const sal_Int16 _nArgPos,
232 SharedConnection& _out_rxConnection,
233 Reference< XInteractionHandler >& _out_rxDocInteractionHandler
234 ) const;
236 /** extracts the source object (table or query) described by the given descriptor,
237 relative to m_xSourceConnection
239 ::std::unique_ptr< ICopyTableSourceObject >
240 impl_extractSourceObject_throw(
241 const Reference< XPropertySet >& _rxDescriptor,
242 sal_Int32& _out_rCommandType
243 ) const;
245 /** extracts the result set to copy records from, and the selection-related aspects, if any.
247 Effectively, this method extracts m_xSourceResultSet, m_aSourceSelection, and m_bSourceSelectionBookmarks.
249 If an inconsistent/insufficent sub set of those properties is present in the descriptor, and exception
250 is thrown.
252 void impl_extractSourceResultSet_throw(
253 const Reference< XPropertySet >& i_rDescriptor
256 /** checks whether the given copy source descriptor contains settings which are not
257 supported (yet)
259 Throws an IllegalArgumentException if the descriptor contains a valid setting, which is
260 not yet supported.
262 void impl_checkForUnsupportedSettings_throw(
263 const Reference< XPropertySet >& _rxSourceDescriptor ) const;
265 /** obtaines the connection described by the given data access descriptor
267 If needed and possible, the method will ask the user, using the interaction
268 handler associated with the database described by the descriptor.
270 All errors are handled with the InteractionHandler associated with the data source,
271 if there is one. Else, they will be silenced (but asserted in non-product builds).
273 @param _rxDataSourceDescriptor
274 the data access descriptor describing the data source whose connection
275 should be obtained. Must not be <NULL/>.
276 @param _out_rxDocInteractionHandler
277 the interaction handler which could be deduced from the descriptor
279 @throws RuntimeException
280 if anything goes seriously wrong.
282 SharedConnection
283 impl_extractConnection_throw(
284 const Reference< XPropertySet >& _rxDataSourceDescriptor,
285 Reference< XInteractionHandler >& _out_rxDocInteractionHandler
286 ) const;
288 /** actually copies the table
290 This method is called after the dialog has been successfully executed.
292 void impl_doCopy_nothrow();
294 /** creates the INSERT INTO statement
295 @param _xTable The destination table.
297 OUString impl_getServerSideCopyStatement_throw( const Reference< XPropertySet >& _xTable );
299 /** creates the statement which, when executed, will produce the source data to copy
301 If the source object refers to a query which contains parameters, those parameters
302 are filled in, using an interaction handler.
304 ::utl::SharedUNOComponent< XPreparedStatement >
305 impl_createSourceStatement_throw() const;
307 /** copies the data rows from the given source result set to the given destination table
309 void impl_copyRows_throw(
310 const Reference< XResultSet >& _rxSourceResultSet,
311 const Reference< XPropertySet >& _rxDestTable
314 /** processes an error which occurred during copying
316 First, all listeners are ask. If a listener tells to cancel or continue copying, this is reported to the
317 method's caller. If a listener tells to ask the user, this is done, and the user's decision is
318 reported to the method's caller.
320 @return
321 <TRUE/> if and only if copying should be continued.
323 bool impl_processCopyError_nothrow(
324 const CopyTableRowEvent& _rEvent );
326 private:
327 Reference<XComponentContext> m_xContext;
329 // attributes
330 sal_Int16 m_nOperation;
331 OUString m_sDestinationTable;
332 Optional< OUString > m_aPrimaryKeyName;
333 bool m_bUseHeaderLineAsColumnNames;
335 // source
336 SharedConnection m_xSourceConnection;
337 sal_Int32 m_nCommandType;
338 ::std::unique_ptr< ICopyTableSourceObject >
339 m_pSourceObject;
340 Reference< XResultSet > m_xSourceResultSet;
341 Sequence< Any > m_aSourceSelection;
342 bool m_bSourceSelectionBookmarks;
344 // destination
345 SharedConnection m_xDestConnection;
347 // other
348 Reference< XInteractionHandler > m_xInteractionHandler;
349 ::cppu::OInterfaceContainerHelper
350 m_aCopyTableListeners;
351 sal_Int16 m_nOverrideExecutionResult;
354 // MethodGuard
355 class CopyTableAccessGuard
357 public:
358 CopyTableAccessGuard( CopyTableWizard& _rWizard )
359 :m_rWizard( _rWizard )
361 m_rWizard.getMutex().acquire();
362 if ( !m_rWizard.isInitialized() )
363 throw NotInitializedException();
366 ~CopyTableAccessGuard()
368 m_rWizard.getMutex().release();
371 private:
372 CopyTableWizard& m_rWizard;
375 CopyTableWizard::CopyTableWizard( const Reference< XComponentContext >& _rxORB )
376 :CopyTableWizard_Base( _rxORB )
377 ,m_xContext( _rxORB )
378 ,m_nOperation( CopyTableOperation::CopyDefinitionAndData )
379 ,m_sDestinationTable()
380 ,m_aPrimaryKeyName( sal_False, "ID" )
381 ,m_bUseHeaderLineAsColumnNames( true )
382 ,m_xSourceConnection()
383 ,m_nCommandType( CommandType::COMMAND )
384 ,m_pSourceObject()
385 ,m_xSourceResultSet()
386 ,m_aSourceSelection()
387 ,m_bSourceSelectionBookmarks( true )
388 ,m_xDestConnection()
389 ,m_aCopyTableListeners( m_aMutex )
390 ,m_nOverrideExecutionResult( -1 )
394 CopyTableWizard::~CopyTableWizard()
396 acquire();
398 // protect some members whose dtor might potentially throw
399 try { m_xSourceConnection.clear(); }
400 catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
401 try { m_xDestConnection.clear(); }
402 catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
404 // TODO: shouldn't we have explicit disposal support? If a listener is registered
405 // at our instance, and perhaps holds this our instance by a hard ref, then we'll never
406 // be destroyed.
407 // However, adding XComponent support to the GenericUNODialog probably requires
408 // some thinking - would it break existing clients which do not call a dispose, then?
411 Reference< XInterface > CopyTableWizard::Create( const Reference< XMultiServiceFactory >& _rxFactory )
413 return *( new CopyTableWizard( comphelper::getComponentContext(_rxFactory) ) );
416 OUString SAL_CALL CopyTableWizard::getImplementationName() throw(RuntimeException, std::exception)
418 return getImplementationName_Static();
421 OUString CopyTableWizard::getImplementationName_Static() throw(RuntimeException)
423 return OUString( "org.openoffice.comp.dbu.CopyTableWizard" );
426 ::comphelper::StringSequence SAL_CALL CopyTableWizard::getSupportedServiceNames() throw(RuntimeException, std::exception)
428 return getSupportedServiceNames_Static();
431 ::comphelper::StringSequence CopyTableWizard::getSupportedServiceNames_Static() throw(RuntimeException)
433 ::comphelper::StringSequence aSupported(1);
434 aSupported.getArray()[0] = "com.sun.star.sdb.application.CopyTableWizard";
435 return aSupported;
438 Reference< XPropertySetInfo > SAL_CALL CopyTableWizard::getPropertySetInfo() throw(RuntimeException, std::exception)
440 Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
441 return xInfo;
444 ::sal_Int16 SAL_CALL CopyTableWizard::getOperation() throw (RuntimeException, std::exception)
446 CopyTableAccessGuard aGuard( *this );
447 return m_nOperation;
450 void SAL_CALL CopyTableWizard::setOperation( ::sal_Int16 _operation ) throw (IllegalArgumentException, RuntimeException, std::exception)
452 CopyTableAccessGuard aGuard( *this );
454 if ( ( _operation != CopyTableOperation::CopyDefinitionAndData )
455 && ( _operation != CopyTableOperation::CopyDefinitionOnly )
456 && ( _operation != CopyTableOperation::CreateAsView )
457 && ( _operation != CopyTableOperation::AppendData )
459 throw IllegalArgumentException( OUString(), *this, 1 );
461 if ( ( _operation == CopyTableOperation::CreateAsView )
462 && !OCopyTableWizard::supportsViews( m_xDestConnection )
464 throw IllegalArgumentException(
465 OUString( ModuleRes( STR_CTW_NO_VIEWS_SUPPORT ) ),
466 *this,
470 m_nOperation = _operation;
473 OUString SAL_CALL CopyTableWizard::getDestinationTableName() throw (RuntimeException, std::exception)
475 CopyTableAccessGuard aGuard( *this );
476 return m_sDestinationTable;
479 void SAL_CALL CopyTableWizard::setDestinationTableName( const OUString& _destinationTableName ) throw (RuntimeException, std::exception)
481 CopyTableAccessGuard aGuard( *this );
482 m_sDestinationTable = _destinationTableName;
485 Optional< OUString > SAL_CALL CopyTableWizard::getCreatePrimaryKey() throw (RuntimeException, std::exception)
487 CopyTableAccessGuard aGuard( *this );
488 return m_aPrimaryKeyName;
491 void SAL_CALL CopyTableWizard::setCreatePrimaryKey( const Optional< OUString >& _newPrimaryKey ) throw (IllegalArgumentException, SQLException, RuntimeException, std::exception)
493 CopyTableAccessGuard aGuard( *this );
495 if ( _newPrimaryKey.IsPresent && !OCopyTableWizard::supportsPrimaryKey( m_xDestConnection ) )
496 throw IllegalArgumentException(
497 OUString( ModuleRes( STR_CTW_NO_PRIMARY_KEY_SUPPORT ) ),
498 *this,
502 m_aPrimaryKeyName = _newPrimaryKey;
505 sal_Bool SAL_CALL CopyTableWizard::getUseHeaderLineAsColumnNames() throw (RuntimeException, std::exception)
507 CopyTableAccessGuard aGuard( *this );
508 return m_bUseHeaderLineAsColumnNames;
511 void SAL_CALL CopyTableWizard::setUseHeaderLineAsColumnNames( sal_Bool _bUseHeaderLineAsColumnNames ) throw (RuntimeException, std::exception)
513 CopyTableAccessGuard aGuard( *this );
514 m_bUseHeaderLineAsColumnNames = _bUseHeaderLineAsColumnNames;
517 void SAL_CALL CopyTableWizard::addCopyTableListener( const Reference< XCopyTableListener >& _rxListener ) throw (RuntimeException, std::exception)
519 CopyTableAccessGuard aGuard( *this );
520 if ( _rxListener.is() )
521 m_aCopyTableListeners.addInterface( _rxListener );
524 void SAL_CALL CopyTableWizard::removeCopyTableListener( const Reference< XCopyTableListener >& _rxListener ) throw (RuntimeException, std::exception)
526 CopyTableAccessGuard aGuard( *this );
527 if ( _rxListener.is() )
528 m_aCopyTableListeners.removeInterface( _rxListener );
531 void SAL_CALL CopyTableWizard::setTitle( const OUString& _rTitle ) throw (RuntimeException, std::exception)
533 CopyTableAccessGuard aGuard( *this );
534 CopyTableWizard_DialogBase::setTitle( _rTitle );
537 ::sal_Int16 SAL_CALL CopyTableWizard::execute( ) throw (RuntimeException, std::exception)
539 CopyTableAccessGuard aGuard( *this );
541 m_nOverrideExecutionResult = -1;
542 sal_Int16 nExecutionResult = CopyTableWizard_DialogBase::execute();
543 if ( m_nOverrideExecutionResult )
544 nExecutionResult = m_nOverrideExecutionResult;
546 return nExecutionResult;
549 OCopyTableWizard& CopyTableWizard::impl_getDialog_throw()
551 OCopyTableWizard* pWizard = dynamic_cast< OCopyTableWizard* >( m_pDialog.get() );
552 if ( !pWizard )
553 throw DisposedException( OUString(), *this );
554 return *pWizard;
557 void CopyTableWizard::impl_attributesToDialog_nothrow( OCopyTableWizard& _rDialog ) const
559 // primary key column
560 _rDialog.setCreatePrimaryKey( m_aPrimaryKeyName.IsPresent, m_aPrimaryKeyName.Value );
561 _rDialog.setUseHeaderLine(m_bUseHeaderLineAsColumnNames);
563 // everything else was passed at construction time already
566 void CopyTableWizard::impl_dialogToAttributes_nothrow( const OCopyTableWizard& _rDialog )
568 m_aPrimaryKeyName.IsPresent = _rDialog.shouldCreatePrimaryKey();
569 if ( m_aPrimaryKeyName.IsPresent )
570 m_aPrimaryKeyName.Value = _rDialog.getPrimaryKeyName();
571 else
572 m_aPrimaryKeyName.Value.clear();
574 m_sDestinationTable = _rDialog.getName();
576 m_nOperation = _rDialog.getOperation();
577 m_bUseHeaderLineAsColumnNames = _rDialog.UseHeaderLine();
580 namespace
582 /** tries to obtain the InteractionHandler associated with a given data source
584 If the data source is a sdb-level data source, it will have a DatabaseDocument associated
585 with it. This doocument may have an InteractionHandler used while loading it.
587 @throws RuntimeException
588 if it occurs during invoking any of the data source's methods, or if any of the involved
589 components violates its contract by not providing the required interfaces
591 Reference< XInteractionHandler > lcl_getInteractionHandler_throw( const Reference< XDataSource >& _rxDataSource, const Reference< XInteractionHandler >& _rFallback )
593 Reference< XInteractionHandler > xHandler( _rFallback );
595 // try to obtain the document model
596 Reference< XModel > xDocumentModel;
597 Reference< XDocumentDataSource > xDocDataSource( _rxDataSource, UNO_QUERY );
598 if ( xDocDataSource.is() )
599 xDocumentModel.set( xDocDataSource->getDatabaseDocument(), UNO_QUERY_THROW );
601 // see whether the document model can provide a handler
602 if ( xDocumentModel.is() )
604 ::comphelper::NamedValueCollection aModelArgs( xDocumentModel->getArgs() );
605 xHandler = aModelArgs.getOrDefault( "InteractionHandler", xHandler );
608 return xHandler;
610 /** tries to obtain the InteractionHandler associated with a given connection
612 If the connection belongs to a sdb-level data source, then this data source
613 is examined for an interaction handler. Else, <NULL/> is returned.
615 @throws RuntimeException
616 if it occurs during invoking any of the data source's methods, or if any of the involved
617 components violates its contract by not providing the required interfaces
619 Reference< XInteractionHandler > lcl_getInteractionHandler_throw( const Reference< XConnection >& _rxConnection, const Reference< XInteractionHandler >& _rFallback )
621 // try whether there is a data source which the connection belongs to
622 Reference< XDataSource > xDataSource;
623 Reference< XChild > xAsChild( _rxConnection, UNO_QUERY );
624 if ( xAsChild.is() )
625 xDataSource.set(xAsChild->getParent(), css::uno::UNO_QUERY);
627 if ( xDataSource.is() )
628 return lcl_getInteractionHandler_throw( xDataSource, _rFallback );
630 return _rFallback;
634 Reference< XPropertySet > CopyTableWizard::impl_ensureDataAccessDescriptor_throw(
635 const Sequence< Any >& _rAllArgs, const sal_Int16 _nArgPos, SharedConnection& _out_rxConnection,
636 Reference< XInteractionHandler >& _out_rxDocInteractionHandler ) const
638 Reference< XPropertySet > xDescriptor;
639 _rAllArgs[ _nArgPos ] >>= xDescriptor;
641 // the descriptor must be non-NULL, of course
642 bool bIsValid = xDescriptor.is();
644 // it must support the proper service
645 if ( bIsValid )
647 Reference< XServiceInfo > xSI( xDescriptor, UNO_QUERY );
648 bIsValid = ( xSI.is()
649 && xSI->supportsService( "com.sun.star.sdb.DataAccessDescriptor" ) );
652 // it must be able to provide a connection
653 if ( bIsValid )
655 _out_rxConnection = impl_extractConnection_throw( xDescriptor, _out_rxDocInteractionHandler );
656 bIsValid = _out_rxConnection.is();
659 if ( !bIsValid )
661 throw IllegalArgumentException(
662 OUString( ModuleRes( STR_CTW_INVALID_DATA_ACCESS_DESCRIPTOR ) ),
663 *const_cast< CopyTableWizard* >( this ),
664 _nArgPos + 1
668 return xDescriptor;
671 namespace
673 bool lcl_hasNonEmptyStringValue_throw( const Reference< XPropertySet >& _rxDescriptor,
674 const Reference< XPropertySetInfo >& rxPSI, const OUString& _rPropertyName )
676 OUString sValue;
677 if ( rxPSI->hasPropertyByName( _rPropertyName ) )
679 OSL_VERIFY( _rxDescriptor->getPropertyValue( _rPropertyName ) >>= sValue );
681 return !sValue.isEmpty();
685 void CopyTableWizard::impl_checkForUnsupportedSettings_throw( const Reference< XPropertySet >& _rxSourceDescriptor ) const
687 OSL_PRECOND( _rxSourceDescriptor.is(), "CopyTableWizard::impl_checkForUnsupportedSettings_throw: illegal argument!" );
688 Reference< XPropertySetInfo > xPSI( _rxSourceDescriptor->getPropertySetInfo(), UNO_SET_THROW );
689 OUString sUnsupportedSetting;
691 const OUString aSettings[] = {
692 OUString(PROPERTY_FILTER), OUString(PROPERTY_ORDER), OUString(PROPERTY_HAVING_CLAUSE), OUString(PROPERTY_GROUP_BY)
694 for ( size_t i=0; i < sizeof( aSettings ) / sizeof( aSettings[0] ); ++i )
696 if ( lcl_hasNonEmptyStringValue_throw( _rxSourceDescriptor, xPSI, aSettings[i] ) )
698 sUnsupportedSetting = aSettings[i];
699 break;
703 if ( !sUnsupportedSetting.isEmpty() )
705 OUString sMessage(
706 OUString(ModuleRes(STR_CTW_ERROR_UNSUPPORTED_SETTING)).
707 replaceFirst("$name$", sUnsupportedSetting));
708 throw IllegalArgumentException(
709 sMessage,
710 *const_cast< CopyTableWizard* >( this ),
717 ::std::unique_ptr< ICopyTableSourceObject > CopyTableWizard::impl_extractSourceObject_throw( const Reference< XPropertySet >& _rxDescriptor, sal_Int32& _out_rCommandType ) const
719 OSL_PRECOND( _rxDescriptor.is() && m_xSourceConnection.is(), "CopyTableWizard::impl_extractSourceObject_throw: illegal arguments!" );
721 Reference< XPropertySetInfo > xPSI( _rxDescriptor->getPropertySetInfo(), UNO_SET_THROW );
722 if ( !xPSI->hasPropertyByName( PROPERTY_COMMAND )
723 || !xPSI->hasPropertyByName( PROPERTY_COMMAND_TYPE )
725 throw IllegalArgumentException("Expecting a table or query specification.",
726 // TODO: resource
727 *const_cast< CopyTableWizard* >( this ), 1);
729 OUString sCommand;
730 _out_rCommandType = CommandType::COMMAND;
731 OSL_VERIFY( _rxDescriptor->getPropertyValue( PROPERTY_COMMAND ) >>= sCommand );
732 OSL_VERIFY( _rxDescriptor->getPropertyValue( PROPERTY_COMMAND_TYPE ) >>= _out_rCommandType );
734 ::std::unique_ptr< ICopyTableSourceObject > pSourceObject;
735 Reference< XNameAccess > xContainer;
736 switch ( _out_rCommandType )
738 case CommandType::TABLE:
740 Reference< XTablesSupplier > xSuppTables( m_xSourceConnection.getTyped(), UNO_QUERY );
741 if ( xSuppTables.is() )
742 xContainer.set( xSuppTables->getTables(), UNO_SET_THROW );
744 break;
745 case CommandType::QUERY:
747 Reference< XQueriesSupplier > xSuppQueries( m_xSourceConnection.getTyped(), UNO_QUERY );
748 if ( xSuppQueries.is() )
749 xContainer.set( xSuppQueries->getQueries(), UNO_SET_THROW );
751 break;
752 default:
753 throw IllegalArgumentException(
754 OUString( ModuleRes( STR_CTW_ONLY_TABLES_AND_QUERIES_SUPPORT ) ),
755 *const_cast< CopyTableWizard* >( this ),
760 if ( xContainer.is() )
762 pSourceObject.reset( new ObjectCopySource( m_xSourceConnection,
763 Reference< XPropertySet >( xContainer->getByName( sCommand ), UNO_QUERY_THROW ) ) );
765 else
767 // our source connection is an SDBC level connection only, not a SDBCX level one
768 // Which means it cannot provide the to-be-copied object as component.
770 if ( _out_rCommandType == CommandType::QUERY )
771 // we cannot copy a query if the connection cannot provide it ...
772 throw IllegalArgumentException(
773 OUString(ModuleRes( STR_CTW_ERROR_NO_QUERY )),
774 *const_cast< CopyTableWizard* >( this ),
777 pSourceObject.reset( new NamedTableCopySource( m_xSourceConnection, sCommand ) );
780 return pSourceObject;
783 void CopyTableWizard::impl_extractSourceResultSet_throw( const Reference< XPropertySet >& i_rDescriptor )
785 Reference< XPropertySetInfo > xPSI( i_rDescriptor->getPropertySetInfo(), UNO_SET_THROW );
787 // extract relevant settings
788 if ( xPSI->hasPropertyByName( PROPERTY_RESULT_SET ) )
789 m_xSourceResultSet.set( i_rDescriptor->getPropertyValue( PROPERTY_RESULT_SET ), UNO_QUERY );
791 if ( xPSI->hasPropertyByName( PROPERTY_SELECTION ) )
792 OSL_VERIFY( i_rDescriptor->getPropertyValue( PROPERTY_SELECTION ) >>= m_aSourceSelection );
794 if ( xPSI->hasPropertyByName( PROPERTY_BOOKMARK_SELECTION ) )
795 OSL_VERIFY( i_rDescriptor->getPropertyValue( PROPERTY_BOOKMARK_SELECTION ) >>= m_bSourceSelectionBookmarks );
797 // sanity checks
798 const bool bHasResultSet = m_xSourceResultSet.is();
799 const bool bHasSelection = ( m_aSourceSelection.getLength() != 0 );
800 if ( bHasSelection && !bHasResultSet )
801 throw IllegalArgumentException("A result set is needed when specifying a selection to copy.",
802 // TODO: resource
803 *this, 1);
805 if ( bHasSelection && m_bSourceSelectionBookmarks )
807 Reference< XRowLocate > xRowLocate( m_xSourceResultSet, UNO_QUERY );
808 if ( !xRowLocate.is() )
810 ::dbtools::throwGenericSQLException(
811 OUString( ModuleRes( STR_CTW_COPY_SOURCE_NEEDS_BOOKMARKS ) ),
812 *this
818 SharedConnection CopyTableWizard::impl_extractConnection_throw( const Reference< XPropertySet >& _rxDataSourceDescriptor,
819 Reference< XInteractionHandler >& _out_rxDocInteractionHandler ) const
821 SharedConnection xConnection;
823 OSL_PRECOND( _rxDataSourceDescriptor.is(), "CopyTableWizard::impl_extractConnection_throw: no descriptor!" );
824 if ( !_rxDataSourceDescriptor.is() )
825 return xConnection;
827 Reference< XInteractionHandler > xInteractionHandler;
831 Reference< XPropertySetInfo > xPSI( _rxDataSourceDescriptor->getPropertySetInfo(), UNO_SET_THROW );
833 // if there's an ActiveConnection, use it
834 if ( xPSI->hasPropertyByName( PROPERTY_ACTIVE_CONNECTION ) )
836 Reference< XConnection > xPure;
837 OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xPure );
838 xConnection.reset( xPure, SharedConnection::NoTakeOwnership );
840 if ( xConnection.is() )
842 xInteractionHandler = lcl_getInteractionHandler_throw( xConnection.getTyped(), m_xInteractionHandler );
843 SAL_WARN_IF( !xInteractionHandler.is(), "dbaccess.ui", "CopyTableWizard::impl_extractConnection_throw: lcl_getInteractionHandler_throw returned nonsense!" );
844 break;
847 // there could be a DataSourceName or a DatabaseLocation, describing the css.sdb.DataSource
848 OUString sDataSource, sDatabaseLocation;
849 if ( xPSI->hasPropertyByName( PROPERTY_DATASOURCENAME ) )
850 OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_DATASOURCENAME ) >>= sDataSource );
851 if ( xPSI->hasPropertyByName( PROPERTY_DATABASE_LOCATION ) )
852 OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_DATABASE_LOCATION ) >>= sDatabaseLocation );
854 // need a DatabaseContext for loading the data source
855 Reference< XDatabaseContext > xDatabaseContext = DatabaseContext::create( m_xContext );
856 Reference< XDataSource > xDataSource;
857 if ( !sDataSource.isEmpty() )
858 xDataSource.set( xDatabaseContext->getByName( sDataSource ), UNO_QUERY_THROW );
859 if ( !xDataSource.is() && !sDatabaseLocation.isEmpty() )
860 xDataSource.set( xDatabaseContext->getByName( sDatabaseLocation ), UNO_QUERY_THROW );
862 if ( xDataSource.is() )
864 // first, try connecting with completion
865 xInteractionHandler = lcl_getInteractionHandler_throw( xDataSource, m_xInteractionHandler );
866 SAL_WARN_IF( !xInteractionHandler.is(), "dbaccess.ui", "CopyTableWizard::impl_extractConnection_throw: lcl_getInteractionHandler_throw returned nonsense!" );
867 if ( xInteractionHandler.is() )
869 Reference< XCompletedConnection > xInteractiveConnection( xDataSource, UNO_QUERY );
870 if ( xInteractiveConnection.is() )
871 xConnection.reset( xInteractiveConnection->connectWithCompletion( xInteractionHandler ), SharedConnection::TakeOwnership );
874 // interactively connecting was not successful or possible -> connect without interaction
875 if ( !xConnection.is() )
877 xConnection.reset( xDataSource->getConnection( OUString(), OUString() ), SharedConnection::TakeOwnership );
881 if ( xConnection.is() )
882 break;
884 // finally, there could be a ConnectionResource/ConnectionInfo
885 OUString sConnectionResource;
886 Sequence< PropertyValue > aConnectionInfo;
887 if ( xPSI->hasPropertyByName( PROPERTY_CONNECTION_RESOURCE ) )
888 OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_CONNECTION_RESOURCE ) >>= sConnectionResource );
889 if ( xPSI->hasPropertyByName( PROPERTY_CONNECTION_INFO ) )
890 OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_CONNECTION_INFO ) >>= aConnectionInfo );
892 Reference< XDriverManager > xDriverManager;
893 try {
894 xDriverManager.set( ConnectionPool::create( m_xContext ), UNO_QUERY_THROW );
895 } catch( const Exception& ) { }
896 if ( !xDriverManager.is() )
897 // no connection pool installed
898 xDriverManager.set( DriverManager::create( m_xContext ), UNO_QUERY_THROW );
900 if ( aConnectionInfo.getLength() )
901 xConnection.set( xDriverManager->getConnectionWithInfo( sConnectionResource, aConnectionInfo ), UNO_SET_THROW );
902 else
903 xConnection.set( xDriverManager->getConnection( sConnectionResource ), UNO_SET_THROW );
905 while ( false );
907 if ( xInteractionHandler != m_xInteractionHandler )
908 _out_rxDocInteractionHandler = xInteractionHandler;
910 return xConnection;
913 ::utl::SharedUNOComponent< XPreparedStatement > CopyTableWizard::impl_createSourceStatement_throw() const
915 OSL_PRECOND( m_xSourceConnection.is(), "CopyTableWizard::impl_createSourceStatement_throw: illegal call!" );
916 if ( !m_xSourceConnection.is() )
917 throw RuntimeException( "CopyTableWizard::impl_createSourceStatement_throw: illegal call!", *const_cast< CopyTableWizard* >( this ));
919 ::utl::SharedUNOComponent< XPreparedStatement > xStatement;
920 switch ( m_nCommandType )
922 case CommandType::TABLE:
923 xStatement.set( m_pSourceObject->getPreparedSelectStatement(), UNO_SET_THROW );
924 break;
926 case CommandType::QUERY:
928 OUString sQueryCommand( m_pSourceObject->getSelectStatement() );
929 xStatement.set( m_pSourceObject->getPreparedSelectStatement(), UNO_SET_THROW );
931 // check whether we have to fill in parameter values
932 // create and fill a composer
934 Reference< XMultiServiceFactory > xFactory( m_xSourceConnection, UNO_QUERY );
935 ::utl::SharedUNOComponent< XSingleSelectQueryComposer > xComposer;
936 if ( xFactory.is() )
937 // note: connections below the sdb-level are allowed to not support the XMultiServiceFactory interface
938 xComposer.set( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY );
940 if ( xComposer.is() )
942 xComposer->setQuery( sQueryCommand );
944 Reference< XParameters > xStatementParams( xStatement, UNO_QUERY );
945 OSL_ENSURE( xStatementParams.is(), "CopyTableWizard::impl_createSourceStatement_throw: no access to the statement's parameters!" );
946 // the statement should be a css.sdbc.PreparedStatement (this is what
947 // we created), and a prepared statement is required to support XParameters
948 if ( xStatementParams.is() )
950 OSL_ENSURE( m_xInteractionHandler.is(),
951 "CopyTableWizard::impl_createSourceStatement_throw: no interaction handler for the parameters request!" );
952 // we should always have an interaction handler - as last fallback, we create an own one in ::initialize
954 if ( m_xInteractionHandler.is() )
955 ::dbtools::askForParameters( xComposer, xStatementParams, m_xSourceConnection, m_xInteractionHandler );
959 break;
961 default:
962 // this should not have survived initialization phase
963 throw RuntimeException("No case matched, this should not have survived the initialization phase", *const_cast< CopyTableWizard* >( this ));
966 return xStatement;
969 namespace
971 class ValueTransfer
973 public:
974 ValueTransfer( const sal_Int32& _rSourcePos, const sal_Int32& _rDestPos, const ::std::vector< sal_Int32 >& _rColTypes,
975 const Reference< XRow >& _rxSource, const Reference< XParameters >& _rxDest )
976 :m_rSourcePos( _rSourcePos )
977 ,m_rDestPos( _rDestPos )
978 ,m_rColTypes( _rColTypes )
979 ,m_xSource( _rxSource )
980 ,m_xDest( _rxDest )
984 template< typename VALUE_TYPE >
985 void transferValue( VALUE_TYPE ( SAL_CALL XRow::*_pGetter )( sal_Int32 ),
986 void (SAL_CALL XParameters::*_pSetter)( sal_Int32, VALUE_TYPE ) )
988 VALUE_TYPE value( (m_xSource.get()->*_pGetter)( m_rSourcePos ) );
989 if ( m_xSource->wasNull() )
990 m_xDest->setNull( m_rDestPos, m_rColTypes[ m_rSourcePos ] );
991 else
992 (m_xDest.get()->*_pSetter)( m_rDestPos, value );
994 template< typename VALUE_TYPE >
995 void transferComplexValue( VALUE_TYPE ( SAL_CALL XRow::*_pGetter )( sal_Int32 ),
996 void (SAL_CALL XParameters::*_pSetter)( sal_Int32, const VALUE_TYPE& ) )
998 const VALUE_TYPE value( (m_xSource.get()->*_pGetter)( m_rSourcePos ) );
1000 if ( m_xSource->wasNull() )
1001 m_xDest->setNull( m_rDestPos, m_rColTypes[ m_rSourcePos ] );
1002 else
1003 (m_xDest.get()->*_pSetter)( m_rDestPos, value );
1006 private:
1007 const sal_Int32& m_rSourcePos;
1008 const sal_Int32& m_rDestPos;
1009 const ::std::vector< sal_Int32 > m_rColTypes;
1010 const Reference< XRow > m_xSource;
1011 const Reference< XParameters > m_xDest;
1015 bool CopyTableWizard::impl_processCopyError_nothrow( const CopyTableRowEvent& _rEvent )
1017 Reference< XCopyTableListener > xListener;
1020 ::cppu::OInterfaceIteratorHelper aIter( m_aCopyTableListeners );
1021 while ( aIter.hasMoreElements() )
1023 xListener.set( aIter.next(), UNO_QUERY_THROW );
1024 sal_Int16 nListenerChoice = xListener->copyRowError( _rEvent );
1025 switch ( nListenerChoice )
1027 case CopyTableContinuation::Proceed: return true; // continue copying
1028 case CopyTableContinuation::CallNextHandler: continue; // continue the loop, ask next listener
1029 case CopyTableContinuation::Cancel: return false; // cancel copying
1030 case CopyTableContinuation::AskUser: break; // stop asking the listeners, ask the user
1032 default:
1033 SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_processCopyError_nothrow: invalid listener response!" );
1034 // ask next listener
1035 continue;
1039 catch( const Exception& )
1041 DBG_UNHANDLED_EXCEPTION();
1044 // no listener felt responsible for the error, or a listener told to ask the user
1048 SQLContext aError;
1049 aError.Context = *this;
1050 aError.Message = OUString( ModuleRes( STR_ERROR_OCCURRED_WHILE_COPYING ) );
1052 ::dbtools::SQLExceptionInfo aInfo( _rEvent.Error );
1053 if ( aInfo.isValid() )
1054 aError.NextException = _rEvent.Error;
1055 else
1057 // a non-SQL exception happened
1058 Exception aException;
1059 OSL_VERIFY( _rEvent.Error >>= aException );
1060 SQLContext aContext;
1061 aContext.Context = aException.Context;
1062 aContext.Message = aException.Message;
1063 aContext.Details = _rEvent.Error.getValueTypeName();
1064 aError.NextException <<= aContext;
1067 ::rtl::Reference< ::comphelper::OInteractionRequest > xRequest( new ::comphelper::OInteractionRequest( makeAny( aError ) ) );
1069 ::rtl::Reference< ::comphelper::OInteractionApprove > xYes = new ::comphelper::OInteractionApprove;
1070 xRequest->addContinuation( xYes.get() );
1071 xRequest->addContinuation( new ::comphelper::OInteractionDisapprove );
1073 OSL_ENSURE( m_xInteractionHandler.is(),
1074 "CopyTableWizard::impl_processCopyError_nothrow: we always should have an interaction handler!" );
1075 if ( m_xInteractionHandler.is() )
1076 m_xInteractionHandler->handle( xRequest.get() );
1078 if ( xYes->wasSelected() )
1079 // continue copying
1080 return true;
1082 catch( const Exception& )
1084 DBG_UNHANDLED_EXCEPTION();
1087 // cancel copying
1088 return false;
1091 void CopyTableWizard::impl_copyRows_throw( const Reference< XResultSet >& _rxSourceResultSet,
1092 const Reference< XPropertySet >& _rxDestTable )
1094 OSL_PRECOND( m_xDestConnection.is(), "CopyTableWizard::impl_copyRows_throw: illegal call!" );
1095 if ( !m_xDestConnection.is() )
1096 throw RuntimeException( "m_xDestConnection is set to null, CopyTableWizard::impl_copyRows_throw: illegal call!", *this );
1098 Reference< XDatabaseMetaData > xDestMetaData( m_xDestConnection->getMetaData(), UNO_QUERY_THROW );
1100 const OCopyTableWizard& rWizard = impl_getDialog_throw();
1101 ODatabaseExport::TPositions aColumnMapping = rWizard.GetColumnPositions();
1102 bool bAutoIncrement = rWizard.shouldCreatePrimaryKey();
1104 Reference< XRow > xRow ( _rxSourceResultSet, UNO_QUERY_THROW );
1105 Reference< XRowLocate > xRowLocate ( _rxSourceResultSet, UNO_QUERY_THROW );
1107 Reference< XResultSetMetaDataSupplier > xSuppResMeta( _rxSourceResultSet, UNO_QUERY_THROW );
1108 Reference< XResultSetMetaData> xMeta( xSuppResMeta->getMetaData() );
1110 // we need a vector which all types
1111 sal_Int32 nCount = xMeta->getColumnCount();
1112 ::std::vector< sal_Int32 > aSourceColTypes;
1113 aSourceColTypes.reserve( nCount + 1 );
1114 aSourceColTypes.push_back( -1 ); // just to avoid a every time i-1 call
1116 ::std::vector< sal_Int32 > aSourcePrec;
1117 aSourcePrec.reserve( nCount + 1 );
1118 aSourcePrec.push_back( -1 ); // just to avoid a every time i-1 call
1120 for ( sal_Int32 k=1; k <= nCount; ++k )
1122 aSourceColTypes.push_back( xMeta->getColumnType( k ) );
1123 aSourcePrec.push_back( xMeta->getPrecision( k ) );
1126 // now create, fill and execute the prepared statement
1127 Reference< XPreparedStatement > xStatement( ODatabaseExport::createPreparedStatment( xDestMetaData, _rxDestTable, aColumnMapping ), UNO_SET_THROW );
1128 Reference< XParameters > xStatementParams( xStatement, UNO_QUERY_THROW );
1130 const bool bSelectedRecordsOnly = m_aSourceSelection.getLength() != 0;
1131 const Any* pSelectedRow = m_aSourceSelection.getConstArray();
1132 const Any* pSelEnd = pSelectedRow + m_aSourceSelection.getLength();
1134 sal_Int32 nRowCount = 0;
1135 bool bContinue = false;
1137 CopyTableRowEvent aCopyEvent;
1138 aCopyEvent.Source = *this;
1139 aCopyEvent.SourceData = _rxSourceResultSet;
1141 do // loop as long as there are more rows or the selection ends
1143 bContinue = false;
1144 if ( bSelectedRecordsOnly )
1146 if ( pSelectedRow != pSelEnd )
1148 if ( m_bSourceSelectionBookmarks )
1150 bContinue = xRowLocate->moveToBookmark( *pSelectedRow );
1152 else
1154 sal_Int32 nPos = 0;
1155 OSL_VERIFY( *pSelectedRow >>= nPos );
1156 bContinue = _rxSourceResultSet->absolute( nPos );
1158 ++pSelectedRow;
1161 else
1162 bContinue = _rxSourceResultSet->next();
1164 if ( !bContinue )
1166 break;
1169 ++nRowCount;
1170 ODatabaseExport::TPositions::const_iterator aPosIter = aColumnMapping.begin();
1171 ODatabaseExport::TPositions::const_iterator aPosEnd = aColumnMapping.end();
1173 aCopyEvent.Error.clear();
1176 bool bInsertAutoIncrement = true;
1177 // notify listeners
1178 m_aCopyTableListeners.notifyEach( &XCopyTableListener::copyingRow, aCopyEvent );
1180 sal_Int32 nDestColumn( 0 );
1181 sal_Int32 nSourceColumn( 1 );
1182 ValueTransfer aTransfer( nSourceColumn, nDestColumn, aSourceColTypes, xRow, xStatementParams );
1184 for ( ; aPosIter != aPosEnd; ++aPosIter )
1186 nDestColumn = aPosIter->first;
1187 if ( nDestColumn == COLUMN_POSITION_NOT_FOUND )
1189 ++nSourceColumn;
1190 // otherwise we don't get the correct value when only the 2nd source column was selected
1191 continue;
1194 if ( bAutoIncrement && bInsertAutoIncrement )
1196 xStatementParams->setInt( 1, nRowCount );
1197 bInsertAutoIncrement = false;
1198 continue;
1201 if ( ( nSourceColumn < 1 ) || ( nSourceColumn >= (sal_Int32)aSourceColTypes.size() ) )
1202 { // ( we have to check here against 1 because the parameters are 1 based)
1203 ::dbtools::throwSQLException("Internal error: invalid column type index.",
1204 ::dbtools::SQL_INVALID_DESCRIPTOR_INDEX, *this);
1207 switch ( aSourceColTypes[ nSourceColumn ] )
1209 case DataType::DOUBLE:
1210 case DataType::REAL:
1211 aTransfer.transferValue( &XRow::getDouble, &XParameters::setDouble );
1212 break;
1214 case DataType::CHAR:
1215 case DataType::VARCHAR:
1216 case DataType::LONGVARCHAR:
1217 case DataType::DECIMAL:
1218 case DataType::NUMERIC:
1219 aTransfer.transferComplexValue( &XRow::getString, &XParameters::setString );
1220 break;
1222 case DataType::BIGINT:
1223 aTransfer.transferValue( &XRow::getLong, &XParameters::setLong );
1224 break;
1226 case DataType::FLOAT:
1227 aTransfer.transferValue( &XRow::getFloat, &XParameters::setFloat );
1228 break;
1230 case DataType::LONGVARBINARY:
1231 case DataType::BINARY:
1232 case DataType::VARBINARY:
1233 aTransfer.transferComplexValue( &XRow::getBytes, &XParameters::setBytes );
1234 break;
1236 case DataType::DATE:
1237 aTransfer.transferComplexValue( &XRow::getDate, &XParameters::setDate );
1238 break;
1240 case DataType::TIME:
1241 aTransfer.transferComplexValue( &XRow::getTime, &XParameters::setTime );
1242 break;
1244 case DataType::TIMESTAMP:
1245 aTransfer.transferComplexValue( &XRow::getTimestamp, &XParameters::setTimestamp );
1246 break;
1248 case DataType::BIT:
1249 if ( aSourcePrec[nSourceColumn] > 1 )
1251 aTransfer.transferComplexValue( &XRow::getBytes, &XParameters::setBytes );
1252 break;
1254 // run through
1255 case DataType::BOOLEAN:
1256 aTransfer.transferValue( &XRow::getBoolean, &XParameters::setBoolean );
1257 break;
1259 case DataType::TINYINT:
1260 aTransfer.transferValue( &XRow::getByte, &XParameters::setByte );
1261 break;
1263 case DataType::SMALLINT:
1264 aTransfer.transferValue( &XRow::getShort, &XParameters::setShort );
1265 break;
1267 case DataType::INTEGER:
1268 aTransfer.transferValue( &XRow::getInt, &XParameters::setInt );
1269 break;
1271 case DataType::BLOB:
1272 aTransfer.transferComplexValue( &XRow::getBlob, &XParameters::setBlob );
1273 break;
1275 case DataType::CLOB:
1276 aTransfer.transferComplexValue( &XRow::getClob, &XParameters::setClob );
1277 break;
1279 default:
1281 OUString aMessage( ModuleRes( STR_CTW_UNSUPPORTED_COLUMN_TYPE ) );
1283 aMessage = aMessage.replaceFirst( "$type$", OUString::number( aSourceColTypes[ nSourceColumn ] ) );
1284 aMessage = aMessage.replaceFirst( "$pos$", OUString::number( nSourceColumn ) );
1286 ::dbtools::throwSQLException(
1287 aMessage,
1288 ::dbtools::SQL_INVALID_SQL_DATA_TYPE,
1289 *this
1293 ++nSourceColumn;
1295 xStatement->executeUpdate();
1297 // notify listeners
1298 m_aCopyTableListeners.notifyEach( &XCopyTableListener::copiedRow, aCopyEvent );
1300 catch( const Exception& )
1302 aCopyEvent.Error = ::cppu::getCaughtException();
1305 if ( aCopyEvent.Error.hasValue() )
1306 bContinue = impl_processCopyError_nothrow( aCopyEvent );
1308 while( bContinue );
1311 void CopyTableWizard::impl_doCopy_nothrow()
1313 Any aError;
1317 OCopyTableWizard& rWizard( impl_getDialog_throw() );
1319 WaitObject aWO( rWizard.GetParent() );
1320 Reference< XPropertySet > xTable;
1322 switch ( rWizard.getOperation() )
1324 case CopyTableOperation::CopyDefinitionOnly:
1325 case CopyTableOperation::CopyDefinitionAndData:
1327 xTable = rWizard.createTable();
1329 if( !xTable.is() )
1331 SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_doCopy_nothrow: createTable should throw here, shouldn't it?" );
1332 break;
1335 if( CopyTableOperation::CopyDefinitionOnly == rWizard.getOperation() )
1336 break;
1338 // run through
1340 case CopyTableOperation::AppendData:
1343 if ( !xTable.is() )
1345 xTable = rWizard.createTable();
1346 if ( !xTable.is() )
1348 SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_doCopy_nothrow: createTable should throw here, shouldn't it?" );
1349 break;
1353 ::utl::SharedUNOComponent< XPreparedStatement > xSourceStatement;
1354 ::utl::SharedUNOComponent< XResultSet > xSourceResultSet;
1356 if ( m_xSourceResultSet.is() )
1358 xSourceResultSet.reset( m_xSourceResultSet, ::utl::SharedUNOComponent< XResultSet >::NoTakeOwnership );
1360 else
1362 const bool bIsSameConnection = ( m_xSourceConnection.getTyped() == m_xDestConnection.getTyped() );
1363 const bool bIsTable = ( CommandType::TABLE == m_nCommandType );
1364 bool bDone = false;
1365 if ( bIsSameConnection && bIsTable )
1367 // try whether the server supports copying via SQL
1370 m_xDestConnection->createStatement()->executeUpdate( impl_getServerSideCopyStatement_throw(xTable) );
1371 bDone = true;
1373 catch( const Exception& )
1375 // this is allowed.
1379 if ( !bDone )
1381 xSourceStatement.set( impl_createSourceStatement_throw(), UNO_SET_THROW );
1382 xSourceResultSet.set( xSourceStatement->executeQuery(), UNO_SET_THROW );
1386 if ( xSourceResultSet.is() )
1387 impl_copyRows_throw( xSourceResultSet, xTable );
1389 break;
1391 case CopyTableOperation::CreateAsView:
1392 rWizard.createView();
1393 break;
1395 default:
1396 SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_doCopy_nothrow: What operation, please?" );
1397 break;
1400 catch( const Exception& )
1402 aError = ::cppu::getCaughtException();
1404 // silence the error of the user cancelling the parameter's dialog
1405 SQLException aSQLError;
1406 if ( ( aError >>= aSQLError ) && ( aSQLError.ErrorCode == ::dbtools::ParameterInteractionCancelled ) )
1408 aError.clear();
1409 m_nOverrideExecutionResult = RET_CANCEL;
1413 if ( aError.hasValue() && m_xInteractionHandler.is() )
1417 ::rtl::Reference< ::comphelper::OInteractionRequest > xRequest( new ::comphelper::OInteractionRequest( aError ) );
1418 m_xInteractionHandler->handle( xRequest.get() );
1420 catch( const Exception& )
1422 DBG_UNHANDLED_EXCEPTION();
1427 OUString CopyTableWizard::impl_getServerSideCopyStatement_throw(const Reference< XPropertySet >& _xTable)
1429 const Reference<XColumnsSupplier> xDestColsSup(_xTable,UNO_QUERY_THROW);
1430 const Sequence< OUString> aDestColumnNames = xDestColsSup->getColumns()->getElementNames();
1431 const Reference< XDatabaseMetaData > xDestMetaData( m_xDestConnection->getMetaData(), UNO_QUERY_THROW );
1432 const OUString sQuote = xDestMetaData->getIdentifierQuoteString();
1433 OUStringBuffer sColumns;
1434 // 1st check if the columns matching
1435 const OCopyTableWizard& rWizard = impl_getDialog_throw();
1436 ODatabaseExport::TPositions aColumnMapping = rWizard.GetColumnPositions();
1437 ODatabaseExport::TPositions::const_iterator aPosIter = aColumnMapping.begin();
1438 for ( sal_Int32 i = 0; aPosIter != aColumnMapping.end() ; ++aPosIter,++i )
1440 if ( COLUMN_POSITION_NOT_FOUND != aPosIter->second )
1442 if ( !sColumns.isEmpty() )
1443 sColumns.append(",");
1444 sColumns.append(sQuote + aDestColumnNames[aPosIter->second - 1] + sQuote);
1447 const OUString sComposedTableName = ::dbtools::composeTableName( xDestMetaData, _xTable, ::dbtools::eInDataManipulation, false, false, true );
1448 OUString sSql("INSERT INTO " + sComposedTableName + " ( " + sColumns.makeStringAndClear() + " ) ( " + m_pSourceObject->getSelectStatement() + " )");
1450 return sSql;
1453 void SAL_CALL CopyTableWizard::initialize( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException, std::exception)
1455 ::osl::MutexGuard aGuard( m_aMutex );
1456 if ( isInitialized() )
1457 throw AlreadyInitializedException( OUString(), *this );
1459 sal_Int32 nArgCount( _rArguments.getLength() );
1460 if ( ( nArgCount != 2 ) && ( nArgCount != 3 ) )
1461 throw IllegalArgumentException(
1462 OUString( ModuleRes( STR_CTW_ILLEGAL_PARAMETER_COUNT ) ),
1463 *this,
1469 if ( nArgCount == 3 )
1470 { // ->createWithInteractionHandler
1471 if ( !( _rArguments[2] >>= m_xInteractionHandler ) )
1472 throw IllegalArgumentException(
1473 OUString(ModuleRes( STR_CTW_ERROR_INVALID_INTERACTIONHANDLER )),
1474 *this,
1478 if ( !m_xInteractionHandler.is() )
1479 m_xInteractionHandler.set( InteractionHandler::createWithParent(m_xContext, 0), UNO_QUERY );
1481 Reference< XInteractionHandler > xSourceDocHandler;
1482 Reference< XPropertySet > xSourceDescriptor( impl_ensureDataAccessDescriptor_throw( _rArguments, 0, m_xSourceConnection, xSourceDocHandler ) );
1483 impl_checkForUnsupportedSettings_throw( xSourceDescriptor );
1484 m_pSourceObject = impl_extractSourceObject_throw( xSourceDescriptor, m_nCommandType );
1485 impl_extractSourceResultSet_throw( xSourceDescriptor );
1487 Reference< XInteractionHandler > xDestDocHandler;
1488 impl_ensureDataAccessDescriptor_throw( _rArguments, 1, m_xDestConnection, xDestDocHandler );
1490 if ( xDestDocHandler.is() && !m_xInteractionHandler.is() )
1491 m_xInteractionHandler = xDestDocHandler;
1493 catch( const RuntimeException& ) { throw; }
1494 catch( const SQLException& ) { throw; }
1495 catch( const Exception& )
1497 throw WrappedTargetException(
1498 OUString( ModuleRes( STR_CTW_ERROR_DURING_INITIALIZATION ) ),
1499 *this,
1500 ::cppu::getCaughtException()
1505 ::cppu::IPropertyArrayHelper& CopyTableWizard::getInfoHelper()
1507 return *getArrayHelper();
1510 ::cppu::IPropertyArrayHelper* CopyTableWizard::createArrayHelper( ) const
1512 Sequence< Property > aProps;
1513 describeProperties( aProps );
1514 return new ::cppu::OPropertyArrayHelper( aProps );
1517 VclPtr<Dialog> CopyTableWizard::createDialog( vcl::Window* _pParent )
1519 OSL_PRECOND( isInitialized(), "CopyTableWizard::createDialog: not initialized!" );
1520 // this should have been prevented in ::execute already
1522 VclPtrInstance<OCopyTableWizard> pWizard(
1523 _pParent,
1524 m_sDestinationTable,
1525 m_nOperation,
1526 *m_pSourceObject,
1527 m_xSourceConnection.getTyped(),
1528 m_xDestConnection.getTyped(),
1529 m_xContext,
1530 m_xInteractionHandler
1533 impl_attributesToDialog_nothrow( *pWizard );
1535 return pWizard;
1538 void CopyTableWizard::executedDialog( sal_Int16 _nExecutionResult )
1540 CopyTableWizard_DialogBase::executedDialog( _nExecutionResult );
1542 if ( _nExecutionResult == RET_OK )
1543 impl_doCopy_nothrow();
1545 // do this after impl_doCopy_nothrow: The attributes may change during copying, for instance
1546 // if the user entered an unqualified table name
1547 impl_dialogToAttributes_nothrow( impl_getDialog_throw() );
1550 } // namespace dbaui
1552 extern "C" void SAL_CALL createRegistryInfo_CopyTableWizard()
1554 static ::dbaui::OMultiInstanceAutoRegistration< ::dbaui::CopyTableWizard > aAutoRegistration;
1557 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */