Version 3.6.0.2, tag libreoffice-3.6.0.2
[LibreOffice.git] / dbaccess / source / ui / uno / copytablewizard.cxx
blobfbeda28fd36b1b2e6723d2736ffb649d8854cc64
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "dbu_reghelper.hxx"
30 #include "dbu_resource.hrc"
31 #include "dbu_uno.hrc"
32 #include "dbustrings.hrc"
33 #include "moduledbu.hxx"
34 #include "sqlmessage.hxx"
35 #include "WCopyTable.hxx"
37 /** === begin UNO includes === **/
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <com/sun/star/sdb/application/XCopyTableWizard.hpp>
40 #include <com/sun/star/sdb/application/CopyTableContinuation.hpp>
41 #include <com/sun/star/sdb/application/CopyTableOperation.hpp>
42 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
43 #include <com/sun/star/lang/NotInitializedException.hpp>
44 #include <com/sun/star/sdbc/XDataSource.hpp>
45 #include <com/sun/star/sdbc/DataType.hpp>
46 #include <com/sun/star/container/XNameAccess.hpp>
47 #include <com/sun/star/container/XChild.hpp>
48 #include <com/sun/star/task/XInteractionHandler.hpp>
49 #include <com/sun/star/frame/XModel.hpp>
50 #include <com/sun/star/sdb/XDocumentDataSource.hpp>
51 #include <com/sun/star/sdb/XCompletedConnection.hpp>
52 #include <com/sun/star/sdb/CommandType.hpp>
53 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
54 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
55 #include <com/sun/star/lang/DisposedException.hpp>
56 #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
57 #include <com/sun/star/sdbc/XParameters.hpp>
58 #include <com/sun/star/sdbc/XRow.hpp>
59 #include <com/sun/star/sdbc/XBlob.hpp>
60 #include <com/sun/star/sdbc/XClob.hpp>
61 #include <com/sun/star/sdbcx/XRowLocate.hpp>
62 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
63 #include <com/sun/star/sdb/SQLContext.hpp>
64 #include <com/sun/star/sdbc/XDriverManager.hpp>
65 /** === end UNO includes === **/
67 #include <comphelper/componentcontext.hxx>
68 #include <comphelper/interaction.hxx>
69 #include <comphelper/namedvaluecollection.hxx>
70 #include <comphelper/proparrhlp.hxx>
71 #include <connectivity/dbexception.hxx>
72 #include <connectivity/dbtools.hxx>
73 #include <cppuhelper/exc_hlp.hxx>
74 #include <cppuhelper/implbase1.hxx>
75 #include <rtl/ustrbuf.hxx>
76 #include <rtl/logfile.hxx>
77 #include <svtools/genericunodialog.hxx>
78 #include <tools/diagnose_ex.h>
79 #include <unotools/sharedunocomponent.hxx>
80 #include <vcl/msgbox.hxx>
81 #include <vcl/waitobj.hxx>
83 //........................................................................
84 namespace dbaui
86 //........................................................................
88 /** === begin UNO using === **/
89 using ::com::sun::star::uno::Reference;
90 using ::com::sun::star::uno::XInterface;
91 using ::com::sun::star::uno::UNO_QUERY;
92 using ::com::sun::star::uno::UNO_QUERY_THROW;
93 using ::com::sun::star::uno::UNO_SET_THROW;
94 using ::com::sun::star::uno::Exception;
95 using ::com::sun::star::uno::RuntimeException;
96 using ::com::sun::star::uno::Any;
97 using ::com::sun::star::uno::makeAny;
98 using ::com::sun::star::uno::Sequence;
99 using ::com::sun::star::beans::XPropertySetInfo;
100 using ::com::sun::star::lang::XMultiServiceFactory;
101 using ::com::sun::star::beans::Property;
102 using ::com::sun::star::sdb::application::XCopyTableWizard;
103 using ::com::sun::star::sdb::application::XCopyTableListener;
104 using ::com::sun::star::sdb::application::CopyTableRowEvent;
105 using ::com::sun::star::beans::Optional;
106 using ::com::sun::star::lang::IllegalArgumentException;
107 using ::com::sun::star::ucb::AlreadyInitializedException;
108 using ::com::sun::star::beans::XPropertySet;
109 using ::com::sun::star::lang::NotInitializedException;
110 using ::com::sun::star::lang::XServiceInfo;
111 using ::com::sun::star::sdbc::XConnection;
112 using ::com::sun::star::sdbc::XDataSource;
113 using ::com::sun::star::container::XNameAccess;
114 using ::com::sun::star::container::XChild;
115 using ::com::sun::star::task::XInteractionHandler;
116 using ::com::sun::star::frame::XModel;
117 using ::com::sun::star::sdb::XDocumentDataSource;
118 using ::com::sun::star::sdb::XCompletedConnection;
119 using ::com::sun::star::lang::WrappedTargetException;
120 using ::com::sun::star::sdbcx::XTablesSupplier;
121 using ::com::sun::star::sdb::XQueriesSupplier;
122 using ::com::sun::star::lang::DisposedException;
123 using ::com::sun::star::sdbc::XPreparedStatement;
124 using ::com::sun::star::sdb::XSingleSelectQueryComposer;
125 using ::com::sun::star::sdbc::XDatabaseMetaData;
126 using ::com::sun::star::sdbcx::XColumnsSupplier;
127 using ::com::sun::star::sdbc::XParameters;
128 using ::com::sun::star::sdbc::XResultSet;
129 using ::com::sun::star::sdbc::XRow;
130 using ::com::sun::star::sdbc::XBlob;
131 using ::com::sun::star::sdbc::XClob;
132 using ::com::sun::star::sdbcx::XRowLocate;
133 using ::com::sun::star::sdbc::XResultSetMetaDataSupplier;
134 using ::com::sun::star::sdbc::XResultSetMetaData;
135 using ::com::sun::star::sdbc::SQLException;
136 using ::com::sun::star::sdb::SQLContext;
137 using ::com::sun::star::sdbc::XDriverManager;
138 using ::com::sun::star::beans::PropertyValue;
139 /** === end UNO using === **/
140 namespace CopyTableOperation = ::com::sun::star::sdb::application::CopyTableOperation;
141 namespace CopyTableContinuation = ::com::sun::star::sdb::application::CopyTableContinuation;
142 namespace CommandType = ::com::sun::star::sdb::CommandType;
143 namespace DataType = ::com::sun::star::sdbc::DataType;
145 typedef ::utl::SharedUNOComponent< XConnection > SharedConnection;
146 typedef Reference< XInteractionHandler > InteractionHandler;
148 //=========================================================================
149 //= CopyTableWizard
150 //=========================================================================
151 typedef ::svt::OGenericUnoDialog CopyTableWizard_DialogBase;
152 typedef ::cppu::ImplInheritanceHelper1 < CopyTableWizard_DialogBase
153 , XCopyTableWizard
154 > CopyTableWizard_Base;
155 class CopyTableWizard
156 :public CopyTableWizard_Base
157 ,public ::comphelper::OPropertyArrayUsageHelper< CopyTableWizard >
159 public:
160 // XServiceInfo
161 virtual ::rtl::OUString SAL_CALL getImplementationName() throw(RuntimeException);
162 virtual ::comphelper::StringSequence SAL_CALL getSupportedServiceNames() throw(RuntimeException);
164 // XServiceInfo - static methods
165 static Sequence< ::rtl::OUString > getSupportedServiceNames_Static(void) throw( RuntimeException );
166 static ::rtl::OUString getImplementationName_Static(void) throw( RuntimeException );
167 static Reference< XInterface > Create( const Reference< XMultiServiceFactory >& );
169 // XCopyTableWizard
170 virtual ::sal_Int16 SAL_CALL getOperation() throw (RuntimeException);
171 virtual void SAL_CALL setOperation( ::sal_Int16 _operation ) throw (IllegalArgumentException, RuntimeException);
172 virtual ::rtl::OUString SAL_CALL getDestinationTableName() throw (RuntimeException);
173 virtual void SAL_CALL setDestinationTableName( const ::rtl::OUString& _destinationTableName ) throw (RuntimeException);
174 virtual Optional< ::rtl::OUString > SAL_CALL getCreatePrimaryKey() throw (RuntimeException);
175 virtual void SAL_CALL setCreatePrimaryKey( const Optional< ::rtl::OUString >& _newPrimaryKey ) throw (IllegalArgumentException, RuntimeException);
176 virtual sal_Bool SAL_CALL getUseHeaderLineAsColumnNames() throw (RuntimeException);
177 virtual void SAL_CALL setUseHeaderLineAsColumnNames( sal_Bool _bUseHeaderLineAsColumnNames ) throw (RuntimeException);
178 virtual void SAL_CALL addCopyTableListener( const Reference< XCopyTableListener >& Listener ) throw (RuntimeException);
179 virtual void SAL_CALL removeCopyTableListener( const Reference< XCopyTableListener >& Listener ) throw (RuntimeException);
181 // XCopyTableWizard::XExecutableDialog
182 virtual void SAL_CALL setTitle( const ::rtl::OUString& aTitle ) throw (RuntimeException);
183 virtual ::sal_Int16 SAL_CALL execute( ) throw (RuntimeException);
185 // XInitialization
186 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException);
188 // XPropertySet
189 virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo() throw(RuntimeException);
190 virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();
192 // OPropertyArrayUsageHelper
193 virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const;
195 public:
196 ::osl::Mutex& getMutex() { return m_aMutex; }
197 bool isInitialized() const { return m_xSourceConnection.is() && m_pSourceObject.get() && m_xDestConnection.is(); }
199 protected:
200 CopyTableWizard( const Reference< XMultiServiceFactory >& _rxORB );
201 ~CopyTableWizard();
203 // OGenericUnoDialog overridables
204 virtual Dialog* createDialog( Window* _pParent );
205 virtual void executedDialog( sal_Int16 _nExecutionResult );
207 private:
208 /// ensures our current attribute values are reflected in the dialog
209 void impl_attributesToDialog_nothrow( OCopyTableWizard& _rDialog ) const;
211 /// ensures the current dialog settings are reflected in our attributes
212 void impl_dialogToAttributes_nothrow( const OCopyTableWizard& _rDialog );
214 /** returns our typed dialog
216 @throws ::com::sun::star::uno::RuntimeException
217 if we don't have a dialog at the moment the method is called
219 OCopyTableWizard&
220 impl_getDialog_throw();
222 /** returns our typed dialog
224 @throws ::com::sun::star::uno::RuntimeException
225 if we don't have a dialog at the moment the method is called
227 const OCopyTableWizard&
228 impl_getDialog_throw() const;
230 /** ensures the given argument sequence contains a valid data access descriptor at the given position
231 @param _rAllArgs
232 the arguments as passed to ->initialize
233 @param _nArgPos
234 the position within ->_rAllArgs which contains the data access descriptor
235 @param _out_rxConnection
236 will, upon successful return, contain the connection for the data source
237 @param _out_rxDocInteractionHandler
238 will, upon successful return, contain the interaction handler which could
239 be deduced from database document described by the descriptor, if any.
240 (It is possible that the descriptor does not allow to deduce a database document,
241 in which case <code>_out_rxDocInteractionHandler</code> will be <NULL/>.)
242 @return the data access descriptor
244 Reference< XPropertySet >
245 impl_ensureDataAccessDescriptor_throw(
246 const Sequence< Any >& _rAllArgs,
247 const sal_Int16 _nArgPos,
248 SharedConnection& _out_rxConnection,
249 InteractionHandler& _out_rxDocInteractionHandler
250 ) const;
252 /** extracts the source object (table or query) described by the given descriptor,
253 relative to m_xSourceConnection
255 SAL_WNODEPRECATED_DECLARATIONS_PUSH
256 ::std::auto_ptr< ICopyTableSourceObject >
257 impl_extractSourceObject_throw(
258 const Reference< XPropertySet >& _rxDescriptor,
259 sal_Int32& _out_rCommandType
260 ) const;
261 SAL_WNODEPRECATED_DECLARATIONS_POP
263 /** extracts the result set to copy records from, and the selection-related aspects, if any.
265 Effectively, this method extracts m_xSourceResultSet, m_aSourceSelection, and m_bSourceSelectionBookmarks.
267 If an inconsistent/insufficent sub set of those properties is present in the descriptor, and exception
268 is thrown.
270 void impl_extractSourceResultSet_throw(
271 const Reference< XPropertySet >& i_rDescriptor
274 /** checks whether the given copy source descriptor contains settings which are not
275 supported (yet)
277 Throws an IllegalArgumentException if the descriptor contains a valid setting, which is
278 not yet supported.
280 void impl_checkForUnsupportedSettings_throw(
281 const Reference< XPropertySet >& _rxSourceDescriptor ) const;
283 /** obtaines the connection described by the given data access descriptor
285 If needed and possible, the method will ask the user, using the interaction
286 handler associated with the database described by the descriptor.
288 All errors are handled with the InteractionHandler associated with the data source,
289 if there is one. Else, they will be silenced (but asserted in non-product builds).
291 @param _rxDataSourceDescriptor
292 the data access descriptor describing the data source whose connection
293 should be obtained. Must not be <NULL/>.
294 @param _out_rxDocInteractionHandler
295 the interaction handler which could be deduced from the descriptor
297 @throws RuntimeException
298 if anything goes seriously wrong.
300 SharedConnection
301 impl_extractConnection_throw(
302 const Reference< XPropertySet >& _rxDataSourceDescriptor,
303 InteractionHandler& _out_rxDocInteractionHandler
304 ) const;
306 /** actually copies the table
308 This method is called after the dialog has been successfully executed.
310 void impl_doCopy_nothrow();
312 /** creates the INSERT INTO statement
313 @param _xTable The destination table.
315 ::rtl::OUString impl_getServerSideCopyStatement_throw( const Reference< XPropertySet >& _xTable );
317 /** creates the statement which, when executed, will produce the source data to copy
319 If the source object refers to a query which contains parameters, those parameters
320 are filled in, using an interaction handler.
322 ::utl::SharedUNOComponent< XPreparedStatement >
323 impl_createSourceStatement_throw() const;
325 /** copies the data rows from the given source result set to the given destination table
327 void impl_copyRows_throw(
328 const Reference< XResultSet >& _rxSourceResultSet,
329 const Reference< XPropertySet >& _rxDestTable
332 /** processes an error which occurred during copying
334 First, all listeners are ask. If a listener tells to cancel or continue copying, this is reported to the
335 method's caller. If a listener tells to ask the user, this is done, and the user's decision is
336 reported to the method's caller.
338 @return
339 <TRUE/> if and only if copying should be continued.
341 bool impl_processCopyError_nothrow(
342 const CopyTableRowEvent& _rEvent );
344 private:
345 ::comphelper::ComponentContext m_aContext;
347 // attributes
348 sal_Int16 m_nOperation;
349 ::rtl::OUString m_sDestinationTable;
350 Optional< ::rtl::OUString > m_aPrimaryKeyName;
351 sal_Bool m_bUseHeaderLineAsColumnNames;
353 // source
354 SharedConnection m_xSourceConnection;
355 sal_Int32 m_nCommandType;
356 SAL_WNODEPRECATED_DECLARATIONS_PUSH
357 ::std::auto_ptr< ICopyTableSourceObject >
358 m_pSourceObject;
359 SAL_WNODEPRECATED_DECLARATIONS_POP
360 Reference< XResultSet > m_xSourceResultSet;
361 Sequence< Any > m_aSourceSelection;
362 sal_Bool m_bSourceSelectionBookmarks;
364 // destination
365 SharedConnection m_xDestConnection;
367 // other
368 InteractionHandler m_xInteractionHandler;
369 ::cppu::OInterfaceContainerHelper
370 m_aCopyTableListeners;
371 sal_Int16 m_nOverrideExecutionResult;
374 //=========================================================================
375 //= MethodGuard
376 //=========================================================================
377 class CopyTableAccessGuard
379 public:
380 CopyTableAccessGuard( CopyTableWizard& _rWizard )
381 :m_rWizard( _rWizard )
383 m_rWizard.getMutex().acquire();
384 if ( !m_rWizard.isInitialized() )
385 throw NotInitializedException();
388 ~CopyTableAccessGuard()
390 m_rWizard.getMutex().release();
393 private:
394 CopyTableWizard& m_rWizard;
397 //=========================================================================
398 //-------------------------------------------------------------------------
399 CopyTableWizard::CopyTableWizard( const Reference< XMultiServiceFactory >& _rxORB )
400 :CopyTableWizard_Base( _rxORB )
401 ,m_aContext( _rxORB )
402 ,m_nOperation( CopyTableOperation::CopyDefinitionAndData )
403 ,m_sDestinationTable()
404 ,m_aPrimaryKeyName( sal_False, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ID" ) ))
405 ,m_bUseHeaderLineAsColumnNames( sal_True )
406 ,m_xSourceConnection()
407 ,m_nCommandType( CommandType::COMMAND )
408 ,m_pSourceObject()
409 ,m_xSourceResultSet()
410 ,m_aSourceSelection()
411 ,m_bSourceSelectionBookmarks( sal_True )
412 ,m_xDestConnection()
413 ,m_aCopyTableListeners( m_aMutex )
414 ,m_nOverrideExecutionResult( -1 )
418 //-------------------------------------------------------------------------
419 CopyTableWizard::~CopyTableWizard()
421 acquire();
423 // protect some members whose dtor might potentially throw
424 try { m_xSourceConnection.clear(); }
425 catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
426 try { m_xDestConnection.clear(); }
427 catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
429 // TODO: shouldn't we have explicit disposal support? If a listener is registered
430 // at our instance, and perhaps holds this our instance by a hard ref, then we'll never
431 // be destroyed.
432 // However, adding XComponent support to the GenericUNODialog probably requires
433 // some thinking - would it break existing clients which do not call a dispose, then?
436 //-------------------------------------------------------------------------
437 Reference< XInterface > CopyTableWizard::Create( const Reference< XMultiServiceFactory >& _rxFactory )
439 return *( new CopyTableWizard( _rxFactory ) );
442 //-------------------------------------------------------------------------
443 ::rtl::OUString SAL_CALL CopyTableWizard::getImplementationName() throw(RuntimeException)
445 return getImplementationName_Static();
448 //-------------------------------------------------------------------------
449 ::rtl::OUString CopyTableWizard::getImplementationName_Static() throw(RuntimeException)
451 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.dbu.CopyTableWizard" ) );
454 //-------------------------------------------------------------------------
455 ::comphelper::StringSequence SAL_CALL CopyTableWizard::getSupportedServiceNames() throw(RuntimeException)
457 return getSupportedServiceNames_Static();
460 //-------------------------------------------------------------------------
461 ::comphelper::StringSequence CopyTableWizard::getSupportedServiceNames_Static() throw(RuntimeException)
463 ::comphelper::StringSequence aSupported(1);
464 aSupported.getArray()[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.application.CopyTableWizard" ) );
465 return aSupported;
468 //-------------------------------------------------------------------------
469 Reference< XPropertySetInfo > SAL_CALL CopyTableWizard::getPropertySetInfo() throw(RuntimeException)
471 Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
472 return xInfo;
475 //--------------------------------------------------------------------
476 ::sal_Int16 SAL_CALL CopyTableWizard::getOperation() throw (RuntimeException)
478 CopyTableAccessGuard aGuard( *this );
479 return m_nOperation;
482 //--------------------------------------------------------------------
483 void SAL_CALL CopyTableWizard::setOperation( ::sal_Int16 _operation ) throw (IllegalArgumentException, RuntimeException)
485 CopyTableAccessGuard aGuard( *this );
487 if ( ( _operation != CopyTableOperation::CopyDefinitionAndData )
488 && ( _operation != CopyTableOperation::CopyDefinitionOnly )
489 && ( _operation != CopyTableOperation::CreateAsView )
490 && ( _operation != CopyTableOperation::AppendData )
492 throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
494 if ( ( _operation == CopyTableOperation::CreateAsView )
495 && !OCopyTableWizard::supportsViews( m_xDestConnection )
497 throw IllegalArgumentException(
498 String( ModuleRes( STR_CTW_NO_VIEWS_SUPPORT ) ),
499 *this,
503 m_nOperation = _operation;
506 //--------------------------------------------------------------------
507 ::rtl::OUString SAL_CALL CopyTableWizard::getDestinationTableName() throw (RuntimeException)
509 CopyTableAccessGuard aGuard( *this );
510 return m_sDestinationTable;
513 //--------------------------------------------------------------------
514 void SAL_CALL CopyTableWizard::setDestinationTableName( const ::rtl::OUString& _destinationTableName ) throw (RuntimeException)
516 CopyTableAccessGuard aGuard( *this );
517 m_sDestinationTable = _destinationTableName;
520 //--------------------------------------------------------------------
521 Optional< ::rtl::OUString > SAL_CALL CopyTableWizard::getCreatePrimaryKey() throw (RuntimeException)
523 CopyTableAccessGuard aGuard( *this );
524 return m_aPrimaryKeyName;
527 //--------------------------------------------------------------------
528 void SAL_CALL CopyTableWizard::setCreatePrimaryKey( const Optional< ::rtl::OUString >& _newPrimaryKey ) throw (IllegalArgumentException, RuntimeException)
530 CopyTableAccessGuard aGuard( *this );
532 if ( _newPrimaryKey.IsPresent && !OCopyTableWizard::supportsPrimaryKey( m_xDestConnection ) )
533 throw IllegalArgumentException(
534 String( ModuleRes( STR_CTW_NO_PRIMARY_KEY_SUPPORT ) ),
535 *this,
539 m_aPrimaryKeyName = _newPrimaryKey;
541 // -----------------------------------------------------------------------------
542 sal_Bool SAL_CALL CopyTableWizard::getUseHeaderLineAsColumnNames() throw (RuntimeException)
544 CopyTableAccessGuard aGuard( *this );
545 return m_bUseHeaderLineAsColumnNames;
547 // -----------------------------------------------------------------------------
548 void SAL_CALL CopyTableWizard::setUseHeaderLineAsColumnNames( sal_Bool _bUseHeaderLineAsColumnNames ) throw (RuntimeException)
550 CopyTableAccessGuard aGuard( *this );
551 m_bUseHeaderLineAsColumnNames = _bUseHeaderLineAsColumnNames;
553 //--------------------------------------------------------------------
554 void SAL_CALL CopyTableWizard::addCopyTableListener( const Reference< XCopyTableListener >& _rxListener ) throw (RuntimeException)
556 CopyTableAccessGuard aGuard( *this );
557 if ( _rxListener.is() )
558 m_aCopyTableListeners.addInterface( _rxListener );
561 //--------------------------------------------------------------------
562 void SAL_CALL CopyTableWizard::removeCopyTableListener( const Reference< XCopyTableListener >& _rxListener ) throw (RuntimeException)
564 CopyTableAccessGuard aGuard( *this );
565 if ( _rxListener.is() )
566 m_aCopyTableListeners.removeInterface( _rxListener );
569 //--------------------------------------------------------------------
570 void SAL_CALL CopyTableWizard::setTitle( const ::rtl::OUString& _rTitle ) throw (RuntimeException)
572 CopyTableAccessGuard aGuard( *this );
573 CopyTableWizard_DialogBase::setTitle( _rTitle );
576 //--------------------------------------------------------------------
577 ::sal_Int16 SAL_CALL CopyTableWizard::execute( ) throw (RuntimeException)
579 CopyTableAccessGuard aGuard( *this );
581 m_nOverrideExecutionResult = -1;
582 sal_Int16 nExecutionResult = CopyTableWizard_DialogBase::execute();
583 if ( m_nOverrideExecutionResult )
584 nExecutionResult = m_nOverrideExecutionResult;
586 return nExecutionResult;
589 //-------------------------------------------------------------------------
590 OCopyTableWizard& CopyTableWizard::impl_getDialog_throw()
592 OCopyTableWizard* pWizard = dynamic_cast< OCopyTableWizard* >( m_pDialog );
593 if ( !pWizard )
594 throw DisposedException( ::rtl::OUString(), *this );
595 return *pWizard;
598 //-------------------------------------------------------------------------
599 const OCopyTableWizard& CopyTableWizard::impl_getDialog_throw() const
601 const OCopyTableWizard* pWizard = dynamic_cast< const OCopyTableWizard* >( m_pDialog );
602 if ( !pWizard )
603 throw DisposedException( ::rtl::OUString(), *const_cast< CopyTableWizard* >( this ) );
604 return *pWizard;
607 //-------------------------------------------------------------------------
608 void CopyTableWizard::impl_attributesToDialog_nothrow( OCopyTableWizard& _rDialog ) const
610 // primary key column
611 _rDialog.setCreatePrimaryKey( m_aPrimaryKeyName.IsPresent, m_aPrimaryKeyName.Value );
612 _rDialog.setUseHeaderLine(m_bUseHeaderLineAsColumnNames);
614 // everything else was passed at construction time already
617 //-------------------------------------------------------------------------
618 void CopyTableWizard::impl_dialogToAttributes_nothrow( const OCopyTableWizard& _rDialog )
620 m_aPrimaryKeyName.IsPresent = _rDialog.shouldCreatePrimaryKey();
621 if ( m_aPrimaryKeyName.IsPresent )
622 m_aPrimaryKeyName.Value = _rDialog.getPrimaryKeyName();
623 else
624 m_aPrimaryKeyName.Value = ::rtl::OUString();
626 m_sDestinationTable = _rDialog.getName();
628 m_nOperation = _rDialog.getOperation();
629 m_bUseHeaderLineAsColumnNames = _rDialog.UseHeaderLine();
632 //-------------------------------------------------------------------------
633 namespace
635 //.....................................................................
636 /** tries to obtain the InteractionHandler associated with a given data source
638 If the data source is a sdb-level data source, it will have a DatabaseDocument associated
639 with it. This doocument may have an InteractionHandler used while loading it.
641 @throws RuntimeException
642 if it occures during invoking any of the data source's methods, or if any of the involved
643 components violates its contract by not providing the required interfaces
645 InteractionHandler lcl_getInteractionHandler_throw( const Reference< XDataSource >& _rxDataSource, const InteractionHandler& _rFallback )
647 InteractionHandler xHandler( _rFallback );
649 // try to obtain the document model
650 Reference< XModel > xDocumentModel;
651 Reference< XDocumentDataSource > xDocDataSource( _rxDataSource, UNO_QUERY );
652 if ( xDocDataSource.is() )
653 xDocumentModel.set( xDocDataSource->getDatabaseDocument(), UNO_QUERY_THROW );
655 // see whether the document model can provide a handler
656 if ( xDocumentModel.is() )
658 ::comphelper::NamedValueCollection aModelArgs( xDocumentModel->getArgs() );
659 xHandler = aModelArgs.getOrDefault( "InteractionHandler", xHandler );
662 return xHandler;
664 //.....................................................................
665 /** tries to obtain the InteractionHandler associated with a given connection
667 If the connection belongs to a sdb-level data source, then this data source
668 is examined for an interaction handler. Else, <NULL/> is returned.
670 @throws RuntimeException
671 if it occures during invoking any of the data source's methods, or if any of the involved
672 components violates its contract by not providing the required interfaces
674 InteractionHandler lcl_getInteractionHandler_throw( const Reference< XConnection >& _rxConnection, const InteractionHandler& _rFallback )
676 // try whether there is a data source which the connection belongs to
677 Reference< XDataSource > xDataSource;
678 Reference< XChild > xAsChild( _rxConnection, UNO_QUERY );
679 if ( xAsChild.is() )
680 xDataSource = xDataSource.query( xAsChild->getParent() );
682 if ( xDataSource.is() )
683 return lcl_getInteractionHandler_throw( xDataSource, _rFallback );
685 return _rFallback;
689 //-------------------------------------------------------------------------
690 Reference< XPropertySet > CopyTableWizard::impl_ensureDataAccessDescriptor_throw(
691 const Sequence< Any >& _rAllArgs, const sal_Int16 _nArgPos, SharedConnection& _out_rxConnection,
692 InteractionHandler& _out_rxDocInteractionHandler ) const
694 Reference< XPropertySet > xDescriptor;
695 _rAllArgs[ _nArgPos ] >>= xDescriptor;
697 // the descriptor must be non-NULL, of course
698 bool bIsValid = xDescriptor.is();
700 // it must support the proper service
701 if ( bIsValid )
703 Reference< XServiceInfo > xSI( xDescriptor, UNO_QUERY );
704 bIsValid = ( xSI.is()
705 && xSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sdb.DataAccessDescriptor" ) ) )
709 // it must be able to provide a connection
710 if ( bIsValid )
712 _out_rxConnection = impl_extractConnection_throw( xDescriptor, _out_rxDocInteractionHandler );
713 bIsValid = _out_rxConnection.is();
716 if ( !bIsValid )
718 throw IllegalArgumentException(
719 String( ModuleRes( STR_CTW_INVALID_DATA_ACCESS_DESCRIPTOR ) ),
720 *const_cast< CopyTableWizard* >( this ),
721 _nArgPos + 1
725 return xDescriptor;
728 //-------------------------------------------------------------------------
729 namespace
731 bool lcl_hasNonEmptyStringValue_throw( const Reference< XPropertySet >& _rxDescriptor,
732 const Reference< XPropertySetInfo > _rxPSI, const ::rtl::OUString& _rPropertyName )
734 ::rtl::OUString sValue;
735 if ( _rxPSI->hasPropertyByName( _rPropertyName ) )
737 OSL_VERIFY( _rxDescriptor->getPropertyValue( _rPropertyName ) >>= sValue );
739 return !sValue.isEmpty();
743 //-------------------------------------------------------------------------
744 void CopyTableWizard::impl_checkForUnsupportedSettings_throw( const Reference< XPropertySet >& _rxSourceDescriptor ) const
746 OSL_PRECOND( _rxSourceDescriptor.is(), "CopyTableWizard::impl_checkForUnsupportedSettings_throw: illegal argument!" );
747 Reference< XPropertySetInfo > xPSI( _rxSourceDescriptor->getPropertySetInfo(), UNO_SET_THROW );
748 ::rtl::OUString sUnsupportedSetting;
750 const ::rtl::OUString aSettings[] = {
751 PROPERTY_FILTER, PROPERTY_ORDER, PROPERTY_HAVING_CLAUSE, PROPERTY_GROUP_BY
753 for ( size_t i=0; i < sizeof( aSettings ) / sizeof( aSettings[0] ); ++i )
755 if ( lcl_hasNonEmptyStringValue_throw( _rxSourceDescriptor, xPSI, aSettings[i] ) )
757 sUnsupportedSetting = aSettings[i];
758 break;
762 if ( !sUnsupportedSetting.isEmpty() )
764 ::rtl::OUString sMessage(
765 rtl::OUString(String(ModuleRes(STR_CTW_ERROR_UNSUPPORTED_SETTING))).
766 replaceFirst("$name$", sUnsupportedSetting));
767 throw IllegalArgumentException(
768 sMessage,
769 *const_cast< CopyTableWizard* >( this ),
776 //-------------------------------------------------------------------------
777 SAL_WNODEPRECATED_DECLARATIONS_PUSH
778 ::std::auto_ptr< ICopyTableSourceObject > CopyTableWizard::impl_extractSourceObject_throw( const Reference< XPropertySet >& _rxDescriptor, sal_Int32& _out_rCommandType ) const
780 OSL_PRECOND( _rxDescriptor.is() && m_xSourceConnection.is(), "CopyTableWizard::impl_extractSourceObject_throw: illegal arguments!" );
782 Reference< XPropertySetInfo > xPSI( _rxDescriptor->getPropertySetInfo(), UNO_SET_THROW );
783 if ( !xPSI->hasPropertyByName( PROPERTY_COMMAND )
784 || !xPSI->hasPropertyByName( PROPERTY_COMMAND_TYPE )
786 throw IllegalArgumentException(
787 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Expecting a table or query specification." ) ),
788 // TODO: resource
789 *const_cast< CopyTableWizard* >( this ),
793 ::rtl::OUString sCommand;
794 _out_rCommandType = CommandType::COMMAND;
795 OSL_VERIFY( _rxDescriptor->getPropertyValue( PROPERTY_COMMAND ) >>= sCommand );
796 OSL_VERIFY( _rxDescriptor->getPropertyValue( PROPERTY_COMMAND_TYPE ) >>= _out_rCommandType );
798 ::std::auto_ptr< ICopyTableSourceObject > pSourceObject;
799 Reference< XNameAccess > xContainer;
800 switch ( _out_rCommandType )
802 case CommandType::TABLE:
804 Reference< XTablesSupplier > xSuppTables( m_xSourceConnection.getTyped(), UNO_QUERY );
805 if ( xSuppTables.is() )
806 xContainer.set( xSuppTables->getTables(), UNO_SET_THROW );
808 break;
809 case CommandType::QUERY:
811 Reference< XQueriesSupplier > xSuppQueries( m_xSourceConnection.getTyped(), UNO_QUERY );
812 if ( xSuppQueries.is() )
813 xContainer.set( xSuppQueries->getQueries(), UNO_SET_THROW );
815 break;
816 default:
817 throw IllegalArgumentException(
818 String( ModuleRes( STR_CTW_ONLY_TABLES_AND_QUERIES_SUPPORT ) ),
819 *const_cast< CopyTableWizard* >( this ),
824 if ( xContainer.is() )
826 pSourceObject.reset( new ObjectCopySource( m_xSourceConnection,
827 Reference< XPropertySet >( xContainer->getByName( sCommand ), UNO_QUERY_THROW ) ) );
829 else
831 // our source connection is an SDBC level connection only, not a SDBCX level one
832 // Which means it cannot provide the to-be-copied object as component.
834 if ( _out_rCommandType == CommandType::QUERY )
835 // we cannot copy a query if the connection cannot provide it ...
836 throw IllegalArgumentException(
837 String(ModuleRes( STR_CTW_ERROR_NO_QUERY )),
838 *const_cast< CopyTableWizard* >( this ),
841 pSourceObject.reset( new NamedTableCopySource( m_xSourceConnection, sCommand ) );
844 return pSourceObject;
846 SAL_WNODEPRECATED_DECLARATIONS_POP
848 //-------------------------------------------------------------------------
849 void CopyTableWizard::impl_extractSourceResultSet_throw( const Reference< XPropertySet >& i_rDescriptor )
851 Reference< XPropertySetInfo > xPSI( i_rDescriptor->getPropertySetInfo(), UNO_SET_THROW );
853 // extract relevant settings
854 if ( xPSI->hasPropertyByName( PROPERTY_RESULT_SET ) )
855 m_xSourceResultSet.set( i_rDescriptor->getPropertyValue( PROPERTY_RESULT_SET ), UNO_QUERY );
857 if ( xPSI->hasPropertyByName( PROPERTY_SELECTION ) )
858 OSL_VERIFY( i_rDescriptor->getPropertyValue( PROPERTY_SELECTION ) >>= m_aSourceSelection );
860 if ( xPSI->hasPropertyByName( PROPERTY_BOOKMARK_SELECTION ) )
861 OSL_VERIFY( i_rDescriptor->getPropertyValue( PROPERTY_BOOKMARK_SELECTION ) >>= m_bSourceSelectionBookmarks );
863 // sanity checks
864 const bool bHasResultSet = m_xSourceResultSet.is();
865 const bool bHasSelection = ( m_aSourceSelection.getLength() != 0 );
866 if ( bHasSelection && !bHasResultSet )
867 throw IllegalArgumentException(
868 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "A result set is needed when specifying a selection to copy." ) ),
869 // TODO: resource
870 *this,
874 if ( bHasSelection && m_bSourceSelectionBookmarks )
876 Reference< XRowLocate > xRowLocate( m_xSourceResultSet, UNO_QUERY );
877 if ( !xRowLocate.is() )
879 ::dbtools::throwGenericSQLException(
880 String( ModuleRes( STR_CTW_COPY_SOURCE_NEEDS_BOOKMARKS ) ),
881 *this
887 //-------------------------------------------------------------------------
888 SharedConnection CopyTableWizard::impl_extractConnection_throw( const Reference< XPropertySet >& _rxDataSourceDescriptor,
889 InteractionHandler& _out_rxDocInteractionHandler ) const
891 SharedConnection xConnection;
893 OSL_PRECOND( _rxDataSourceDescriptor.is(), "CopyTableWizard::impl_extractConnection_throw: no descriptor!" );
894 if ( !_rxDataSourceDescriptor.is() )
895 return xConnection;
897 InteractionHandler xInteractionHandler;
901 Reference< XPropertySetInfo > xPSI( _rxDataSourceDescriptor->getPropertySetInfo(), UNO_SET_THROW );
903 // if there's an ActiveConnection, use it
904 if ( xPSI->hasPropertyByName( PROPERTY_ACTIVE_CONNECTION ) )
906 Reference< XConnection > xPure;
907 OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xPure );
908 xConnection.reset( xPure, SharedConnection::NoTakeOwnership );
910 if ( xConnection.is() )
912 xInteractionHandler = lcl_getInteractionHandler_throw( xConnection.getTyped(), m_xInteractionHandler );
913 OSL_POSTCOND( xInteractionHandler.is(), "CopyTableWizard::impl_extractConnection_throw: lcl_getInteractionHandler_throw returned nonsense!" );
914 break;
917 // there could be a DataSourceName or a DatabaseLocation, describing the css.sdb.DataSource
918 ::rtl::OUString sDataSource, sDatabaseLocation;
919 if ( xPSI->hasPropertyByName( PROPERTY_DATASOURCENAME ) )
920 OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_DATASOURCENAME ) >>= sDataSource );
921 if ( xPSI->hasPropertyByName( PROPERTY_DATABASE_LOCATION ) )
922 OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_DATABASE_LOCATION ) >>= sDatabaseLocation );
924 // need a DatabaseContext for loading the data source
925 Reference< XNameAccess > xDatabaseContext( m_aContext.createComponent( "com.sun.star.sdb.DatabaseContext" ), UNO_QUERY_THROW );
926 Reference< XDataSource > xDataSource;
927 if ( !sDataSource.isEmpty() )
928 xDataSource.set( xDatabaseContext->getByName( sDataSource ), UNO_QUERY_THROW );
929 if ( !xDataSource.is() && !sDatabaseLocation.isEmpty() )
930 xDataSource.set( xDatabaseContext->getByName( sDatabaseLocation ), UNO_QUERY_THROW );
932 if ( xDataSource.is() )
934 // first, try connecting with completion
935 xInteractionHandler = lcl_getInteractionHandler_throw( xDataSource, m_xInteractionHandler );
936 OSL_POSTCOND( xInteractionHandler.is(), "CopyTableWizard::impl_extractConnection_throw: lcl_getInteractionHandler_throw returned nonsense!" );
937 if ( xInteractionHandler.is() )
939 Reference< XCompletedConnection > xInteractiveConnection( xDataSource, UNO_QUERY );
940 if ( xInteractiveConnection.is() )
941 xConnection.reset( xInteractiveConnection->connectWithCompletion( xInteractionHandler ), SharedConnection::TakeOwnership );
944 // interactively connecting was not successful or possible -> connect without interaction
945 if ( !xConnection.is() )
947 xConnection.reset( xDataSource->getConnection( ::rtl::OUString(), ::rtl::OUString() ), SharedConnection::TakeOwnership );
951 if ( xConnection.is() )
952 break;
954 // finally, there could be a ConnectionResource/ConnectionInfo
955 ::rtl::OUString sConnectionResource;
956 Sequence< PropertyValue > aConnectionInfo;
957 if ( xPSI->hasPropertyByName( PROPERTY_CONNECTION_RESOURCE ) )
958 OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_CONNECTION_RESOURCE ) >>= sConnectionResource );
959 if ( xPSI->hasPropertyByName( PROPERTY_CONNECTION_INFO ) )
960 OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_CONNECTION_INFO ) >>= aConnectionInfo );
962 Reference< XDriverManager > xDriverManager;
963 xDriverManager.set( m_aContext.createComponent( "com.sun.star.sdbc.ConnectionPool" ), UNO_QUERY );
964 if ( !xDriverManager.is() )
965 // no connection pool installed
966 xDriverManager.set( m_aContext.createComponent( "com.sun.star.sdbc.DriverManager" ), UNO_QUERY_THROW );
968 if ( aConnectionInfo.getLength() )
969 xConnection.set( xDriverManager->getConnectionWithInfo( sConnectionResource, aConnectionInfo ), UNO_SET_THROW );
970 else
971 xConnection.set( xDriverManager->getConnection( sConnectionResource ), UNO_SET_THROW );
973 while ( false );
975 if ( xInteractionHandler != m_xInteractionHandler )
976 _out_rxDocInteractionHandler = xInteractionHandler;
978 return xConnection;
981 //-------------------------------------------------------------------------
982 ::utl::SharedUNOComponent< XPreparedStatement > CopyTableWizard::impl_createSourceStatement_throw() const
984 OSL_PRECOND( m_xSourceConnection.is(), "CopyTableWizard::impl_createSourceStatement_throw: illegal call!" );
985 if ( !m_xSourceConnection.is() )
986 throw RuntimeException( "CopyTableWizard::impl_createSourceStatement_throw: illegal call!", *const_cast< CopyTableWizard* >( this ));
988 ::utl::SharedUNOComponent< XPreparedStatement > xStatement;
989 switch ( m_nCommandType )
991 case CommandType::TABLE:
992 xStatement.set( m_pSourceObject->getPreparedSelectStatement(), UNO_SET_THROW );
993 break;
995 case CommandType::QUERY:
997 ::rtl::OUString sQueryCommand( m_pSourceObject->getSelectStatement() );
998 xStatement.set( m_pSourceObject->getPreparedSelectStatement(), UNO_SET_THROW );
1000 // check whether we have to fill in parameter values
1001 // create and fill a composer
1003 Reference< XMultiServiceFactory > xFactory( m_xSourceConnection, UNO_QUERY );
1004 ::utl::SharedUNOComponent< XSingleSelectQueryComposer > xComposer;
1005 if ( xFactory.is() )
1006 // note: connections below the sdb-level are allowed to not support the XMultiServiceFactory interface
1007 xComposer.set( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY );
1009 if ( xComposer.is() )
1011 xComposer->setQuery( sQueryCommand );
1013 Reference< XParameters > xStatementParams( xStatement, UNO_QUERY );
1014 OSL_ENSURE( xStatementParams.is(), "CopyTableWizard::impl_createSourceStatement_throw: no access to the statement's parameters!" );
1015 // the statement should be a css.sdbc.PreparedStatement (this is what
1016 // we created), and a prepared statement is required to support XParameters
1017 if ( xStatementParams.is() )
1019 OSL_ENSURE( m_xInteractionHandler.is(),
1020 "CopyTableWizard::impl_createSourceStatement_throw: no interaction handler for the parameters request!" );
1021 // we should always have an interaction handler - as last fallback, we create an own one in ::initialize
1023 if ( m_xInteractionHandler.is() )
1024 ::dbtools::askForParameters( xComposer, xStatementParams, m_xSourceConnection, m_xInteractionHandler );
1028 break;
1030 default:
1031 // this should not have survived initialization phase
1032 throw RuntimeException("No case matched, this should not have survived the initialization phase", *const_cast< CopyTableWizard* >( this ));
1035 return xStatement;
1038 //-------------------------------------------------------------------------
1039 namespace
1041 class ValueTransfer
1043 public:
1044 ValueTransfer( const sal_Int32& _rSourcePos, const sal_Int32& _rDestPos, const ::std::vector< sal_Int32 >& _rColTypes,
1045 const Reference< XRow >& _rxSource, const Reference< XParameters >& _rxDest )
1046 :m_rSourcePos( _rSourcePos )
1047 ,m_rDestPos( _rDestPos )
1048 ,m_rColTypes( _rColTypes )
1049 ,m_xSource( _rxSource )
1050 ,m_xDest( _rxDest )
1054 template< typename VALUE_TYPE >
1055 void transferValue( VALUE_TYPE ( SAL_CALL XRow::*_pGetter )( sal_Int32 ),
1056 void (SAL_CALL XParameters::*_pSetter)( sal_Int32, VALUE_TYPE ) )
1058 VALUE_TYPE value( (m_xSource.get()->*_pGetter)( m_rSourcePos ) );
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 );
1064 template< typename VALUE_TYPE >
1065 void transferComplexValue( VALUE_TYPE ( SAL_CALL XRow::*_pGetter )( sal_Int32 ),
1066 void (SAL_CALL XParameters::*_pSetter)( sal_Int32, const VALUE_TYPE& ) )
1068 const VALUE_TYPE value( (m_xSource.get()->*_pGetter)( m_rSourcePos ) );
1070 if ( m_xSource->wasNull() )
1071 m_xDest->setNull( m_rDestPos, m_rColTypes[ m_rSourcePos ] );
1072 else
1073 (m_xDest.get()->*_pSetter)( m_rDestPos, value );
1076 private:
1077 const sal_Int32& m_rSourcePos;
1078 const sal_Int32& m_rDestPos;
1079 const ::std::vector< sal_Int32 > m_rColTypes;
1080 const Reference< XRow > m_xSource;
1081 const Reference< XParameters > m_xDest;
1085 //-------------------------------------------------------------------------
1086 bool CopyTableWizard::impl_processCopyError_nothrow( const CopyTableRowEvent& _rEvent )
1088 Reference< XCopyTableListener > xListener;
1091 ::cppu::OInterfaceIteratorHelper aIter( m_aCopyTableListeners );
1092 while ( aIter.hasMoreElements() )
1094 xListener.set( aIter.next(), UNO_QUERY_THROW );
1095 sal_Int16 nListenerChoice = xListener->copyRowError( _rEvent );
1096 switch ( nListenerChoice )
1098 case CopyTableContinuation::Proceed: return true; // continue copying
1099 case CopyTableContinuation::CallNextHandler: continue; // continue the loop, ask next listener
1100 case CopyTableContinuation::Cancel: return false; // cancel copying
1101 case CopyTableContinuation::AskUser: break; // stop asking the listeners, ask the user
1103 default:
1104 OSL_FAIL( "CopyTableWizard::impl_processCopyError_nothrow: invalid listener response!" );
1105 // ask next listener
1106 continue;
1110 catch( const Exception& )
1112 DBG_UNHANDLED_EXCEPTION();
1115 // no listener felt responsible for the error, or a listener told to ask the user
1119 SQLContext aError;
1120 aError.Context = *this;
1121 aError.Message = String( ModuleRes( STR_ERROR_OCCURRED_WHILE_COPYING ) );
1123 ::dbtools::SQLExceptionInfo aInfo( _rEvent.Error );
1124 if ( aInfo.isValid() )
1125 aError.NextException = _rEvent.Error;
1126 else
1128 // a non-SQL exception happend
1129 Exception aException;
1130 OSL_VERIFY( _rEvent.Error >>= aException );
1131 SQLContext aContext;
1132 aContext.Context = aException.Context;
1133 aContext.Message = aException.Message;
1134 aContext.Details = _rEvent.Error.getValueTypeName();
1135 aError.NextException <<= aContext;
1138 ::rtl::Reference< ::comphelper::OInteractionRequest > xRequest( new ::comphelper::OInteractionRequest( makeAny( aError ) ) );
1140 ::rtl::Reference< ::comphelper::OInteractionApprove > xYes = new ::comphelper::OInteractionApprove;
1141 xRequest->addContinuation( xYes.get() );
1142 xRequest->addContinuation( new ::comphelper::OInteractionDisapprove );
1144 OSL_ENSURE( m_xInteractionHandler.is(),
1145 "CopyTableWizard::impl_processCopyError_nothrow: we always should have an interaction handler!" );
1146 if ( m_xInteractionHandler.is() )
1147 m_xInteractionHandler->handle( xRequest.get() );
1149 if ( xYes->wasSelected() )
1150 // continue copying
1151 return true;
1153 catch( const Exception& )
1155 DBG_UNHANDLED_EXCEPTION();
1158 // cancel copying
1159 return false;
1162 //-------------------------------------------------------------------------
1163 void CopyTableWizard::impl_copyRows_throw( const Reference< XResultSet >& _rxSourceResultSet,
1164 const Reference< XPropertySet >& _rxDestTable )
1166 OSL_PRECOND( m_xDestConnection.is(), "CopyTableWizard::impl_copyRows_throw: illegal call!" );
1167 if ( !m_xDestConnection.is() )
1168 throw RuntimeException( "m_xDestConnection is set to null, CopyTableWizard::impl_copyRows_throw: illegal call!", *this );
1170 Reference< XDatabaseMetaData > xDestMetaData( m_xDestConnection->getMetaData(), UNO_QUERY_THROW );
1172 const OCopyTableWizard& rWizard = impl_getDialog_throw();
1173 ODatabaseExport::TPositions aColumnMapping = rWizard.GetColumnPositions();
1174 bool bAutoIncrement = rWizard.shouldCreatePrimaryKey();
1176 Reference< XRow > xRow ( _rxSourceResultSet, UNO_QUERY_THROW );
1177 Reference< XRowLocate > xRowLocate ( _rxSourceResultSet, UNO_QUERY_THROW );
1179 Reference< XResultSetMetaDataSupplier > xSuppResMeta( _rxSourceResultSet, UNO_QUERY_THROW );
1180 Reference< XResultSetMetaData> xMeta( xSuppResMeta->getMetaData() );
1182 // we need a vector which all types
1183 sal_Int32 nCount = xMeta->getColumnCount();
1184 ::std::vector< sal_Int32 > aSourceColTypes;
1185 aSourceColTypes.reserve( nCount + 1 );
1186 aSourceColTypes.push_back( -1 ); // just to avoid a everytime i-1 call
1188 ::std::vector< sal_Int32 > aSourcePrec;
1189 aSourcePrec.reserve( nCount + 1 );
1190 aSourcePrec.push_back( -1 ); // just to avoid a everytime i-1 call
1192 for ( sal_Int32 k=1; k <= nCount; ++k )
1194 aSourceColTypes.push_back( xMeta->getColumnType( k ) );
1195 aSourcePrec.push_back( xMeta->getPrecision( k ) );
1198 // now create, fill and execute the prepared statement
1199 Reference< XPreparedStatement > xStatement( ODatabaseExport::createPreparedStatment( xDestMetaData, _rxDestTable, aColumnMapping ), UNO_SET_THROW );
1200 Reference< XParameters > xStatementParams( xStatement, UNO_QUERY_THROW );
1202 const bool bSelectedRecordsOnly = m_aSourceSelection.getLength() != 0;
1203 const Any* pSelectedRow = m_aSourceSelection.getConstArray();
1204 const Any* pSelEnd = pSelectedRow + m_aSourceSelection.getLength();
1206 sal_Int32 nRowCount = 0;
1207 bool bContinue = false;
1209 CopyTableRowEvent aCopyEvent;
1210 aCopyEvent.Source = *this;
1211 aCopyEvent.SourceData = _rxSourceResultSet;
1213 do // loop as long as there are more rows or the selection ends
1215 bContinue = false;
1216 if ( bSelectedRecordsOnly )
1218 if ( pSelectedRow != pSelEnd )
1220 if ( m_bSourceSelectionBookmarks )
1222 bContinue = xRowLocate->moveToBookmark( *pSelectedRow );
1224 else
1226 sal_Int32 nPos = 0;
1227 OSL_VERIFY( *pSelectedRow >>= nPos );
1228 bContinue = _rxSourceResultSet->absolute( nPos );
1230 ++pSelectedRow;
1233 else
1234 bContinue = _rxSourceResultSet->next();
1236 if ( !bContinue )
1238 break;
1241 ++nRowCount;
1242 sal_Bool bInsertAutoIncrement = sal_True;
1243 ODatabaseExport::TPositions::const_iterator aPosIter = aColumnMapping.begin();
1244 ODatabaseExport::TPositions::const_iterator aPosEnd = aColumnMapping.end();
1246 aCopyEvent.Error.clear();
1249 // notify listeners
1250 m_aCopyTableListeners.notifyEach( &XCopyTableListener::copyingRow, aCopyEvent );
1252 sal_Int32 nDestColumn( 0 );
1253 sal_Int32 nSourceColumn( 1 );
1254 ValueTransfer aTransfer( nSourceColumn, nDestColumn, aSourceColTypes, xRow, xStatementParams );
1256 for ( ; aPosIter != aPosEnd; ++aPosIter )
1258 nDestColumn = aPosIter->first;
1259 if ( nDestColumn == COLUMN_POSITION_NOT_FOUND )
1261 ++nSourceColumn;
1262 // otherwise we don't get the correct value when only the 2nd source column was selected
1263 continue;
1266 if ( bAutoIncrement && bInsertAutoIncrement )
1268 xStatementParams->setInt( 1, nRowCount );
1269 bInsertAutoIncrement = sal_False;
1270 continue;
1273 if ( ( nSourceColumn < 1 ) || ( nSourceColumn >= (sal_Int32)aSourceColTypes.size() ) )
1274 { // ( we have to check here against 1 because the parameters are 1 based)
1275 ::dbtools::throwSQLException(
1276 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Internal error: invalid column type index." ) ),
1277 ::dbtools::SQL_INVALID_DESCRIPTOR_INDEX,
1278 *this
1282 switch ( aSourceColTypes[ nSourceColumn ] )
1284 case DataType::DOUBLE:
1285 case DataType::REAL:
1286 aTransfer.transferValue( &XRow::getDouble, &XParameters::setDouble );
1287 break;
1289 case DataType::CHAR:
1290 case DataType::VARCHAR:
1291 case DataType::LONGVARCHAR:
1292 case DataType::DECIMAL:
1293 case DataType::NUMERIC:
1294 aTransfer.transferComplexValue( &XRow::getString, &XParameters::setString );
1295 break;
1297 case DataType::BIGINT:
1298 aTransfer.transferValue( &XRow::getLong, &XParameters::setLong );
1299 break;
1301 case DataType::FLOAT:
1302 aTransfer.transferValue( &XRow::getFloat, &XParameters::setFloat );
1303 break;
1305 case DataType::LONGVARBINARY:
1306 case DataType::BINARY:
1307 case DataType::VARBINARY:
1308 aTransfer.transferComplexValue( &XRow::getBytes, &XParameters::setBytes );
1309 break;
1311 case DataType::DATE:
1312 aTransfer.transferComplexValue( &XRow::getDate, &XParameters::setDate );
1313 break;
1315 case DataType::TIME:
1316 aTransfer.transferComplexValue( &XRow::getTime, &XParameters::setTime );
1317 break;
1319 case DataType::TIMESTAMP:
1320 aTransfer.transferComplexValue( &XRow::getTimestamp, &XParameters::setTimestamp );
1321 break;
1323 case DataType::BIT:
1324 if ( aSourcePrec[nSourceColumn] > 1 )
1326 aTransfer.transferComplexValue( &XRow::getBytes, &XParameters::setBytes );
1327 break;
1329 // run through
1330 case DataType::BOOLEAN:
1331 aTransfer.transferValue( &XRow::getBoolean, &XParameters::setBoolean );
1332 break;
1334 case DataType::TINYINT:
1335 aTransfer.transferValue( &XRow::getByte, &XParameters::setByte );
1336 break;
1338 case DataType::SMALLINT:
1339 aTransfer.transferValue( &XRow::getShort, &XParameters::setShort );
1340 break;
1342 case DataType::INTEGER:
1343 aTransfer.transferValue( &XRow::getInt, &XParameters::setInt );
1344 break;
1346 case DataType::BLOB:
1347 aTransfer.transferComplexValue( &XRow::getBlob, &XParameters::setBlob );
1348 break;
1350 case DataType::CLOB:
1351 aTransfer.transferComplexValue( &XRow::getClob, &XParameters::setClob );
1352 break;
1354 default:
1356 ::rtl::OUString aMessage( String( ModuleRes( STR_CTW_UNSUPPORTED_COLUMN_TYPE ) ) );
1358 aMessage.replaceAt( aMessage.indexOfAsciiL( "$type$", 6 ), 6, ::rtl::OUString::valueOf( aSourceColTypes[ nSourceColumn ] ) );
1359 aMessage.replaceAt( aMessage.indexOfAsciiL( "$pos$", 5 ), 5, ::rtl::OUString::valueOf( nSourceColumn ) );
1361 ::dbtools::throwSQLException(
1362 aMessage,
1363 ::dbtools::SQL_INVALID_SQL_DATA_TYPE,
1364 *this
1368 ++nSourceColumn;
1370 xStatement->executeUpdate();
1372 // notify listeners
1373 m_aCopyTableListeners.notifyEach( &XCopyTableListener::copiedRow, aCopyEvent );
1375 catch( const Exception& )
1377 aCopyEvent.Error = ::cppu::getCaughtException();
1380 if ( aCopyEvent.Error.hasValue() )
1381 bContinue = impl_processCopyError_nothrow( aCopyEvent );
1383 while( bContinue );
1385 //-------------------------------------------------------------------------
1386 void CopyTableWizard::impl_doCopy_nothrow()
1388 Any aError;
1392 OCopyTableWizard& rWizard( impl_getDialog_throw() );
1394 WaitObject aWO( rWizard.GetParent() );
1395 Reference< XPropertySet > xTable;
1397 switch ( rWizard.getOperation() )
1399 case CopyTableOperation::CopyDefinitionOnly:
1400 case CopyTableOperation::CopyDefinitionAndData:
1402 xTable = rWizard.createTable();
1404 if( !xTable.is() )
1406 OSL_FAIL( "CopyTableWizard::impl_doCopy_nothrow: createTable should throw here, shouldn't it?" );
1407 break;
1410 if( CopyTableOperation::CopyDefinitionOnly == rWizard.getOperation() )
1411 break;
1413 // run through
1415 case CopyTableOperation::AppendData:
1418 if ( !xTable.is() )
1420 xTable = rWizard.createTable();
1421 if ( !xTable.is() )
1423 OSL_FAIL( "CopyTableWizard::impl_doCopy_nothrow: createTable should throw here, shouldn't it?" );
1424 break;
1428 ::utl::SharedUNOComponent< XPreparedStatement > xSourceStatement;
1429 ::utl::SharedUNOComponent< XResultSet > xSourceResultSet;
1431 if ( m_xSourceResultSet.is() )
1433 xSourceResultSet.reset( m_xSourceResultSet, ::utl::SharedUNOComponent< XResultSet >::NoTakeOwnership );
1435 else
1437 const bool bIsSameConnection = ( m_xSourceConnection.getTyped() == m_xDestConnection.getTyped() );
1438 const bool bIsTable = ( CommandType::TABLE == m_nCommandType );
1439 bool bDone = false;
1440 if ( bIsSameConnection && bIsTable )
1442 // try whether the server supports copying via SQL
1445 m_xDestConnection->createStatement()->executeUpdate( impl_getServerSideCopyStatement_throw(xTable) );
1446 bDone = true;
1448 catch( const Exception& )
1450 // this is allowed.
1454 if ( !bDone )
1456 xSourceStatement.set( impl_createSourceStatement_throw(), UNO_SET_THROW );
1457 xSourceResultSet.set( xSourceStatement->executeQuery(), UNO_SET_THROW );
1461 if ( xSourceResultSet.is() )
1462 impl_copyRows_throw( xSourceResultSet, xTable );
1464 break;
1466 case CopyTableOperation::CreateAsView:
1467 rWizard.createView();
1468 break;
1470 default:
1471 OSL_FAIL( "CopyTableWizard::impl_doCopy_nothrow: What operation, please?" );
1472 break;
1475 catch( const Exception& )
1477 aError = ::cppu::getCaughtException();
1479 // silence the error of the user cancelling the parameter's dialog
1480 SQLException aSQLError;
1481 if ( ( aError >>= aSQLError ) && ( aSQLError.ErrorCode == ::dbtools::ParameterInteractionCancelled ) )
1483 aError.clear();
1484 m_nOverrideExecutionResult = RET_CANCEL;
1488 if ( aError.hasValue() && m_xInteractionHandler.is() )
1492 ::rtl::Reference< ::comphelper::OInteractionRequest > xRequest( new ::comphelper::OInteractionRequest( aError ) );
1493 m_xInteractionHandler->handle( xRequest.get() );
1495 catch( const Exception& )
1497 DBG_UNHANDLED_EXCEPTION();
1501 // -----------------------------------------------------------------------------
1502 ::rtl::OUString CopyTableWizard::impl_getServerSideCopyStatement_throw(const Reference< XPropertySet >& _xTable)
1504 const Reference<XColumnsSupplier> xDestColsSup(_xTable,UNO_QUERY_THROW);
1505 const Sequence< ::rtl::OUString> aDestColumnNames = xDestColsSup->getColumns()->getElementNames();
1506 const Sequence< ::rtl::OUString > aColumnNames = m_pSourceObject->getColumnNames();
1507 const Reference< XDatabaseMetaData > xDestMetaData( m_xDestConnection->getMetaData(), UNO_QUERY_THROW );
1508 const ::rtl::OUString sQuote = xDestMetaData->getIdentifierQuoteString();
1509 ::rtl::OUStringBuffer sColumns;
1510 // 1st check if the columns matching
1511 const OCopyTableWizard& rWizard = impl_getDialog_throw();
1512 ODatabaseExport::TPositions aColumnMapping = rWizard.GetColumnPositions();
1513 ODatabaseExport::TPositions::const_iterator aPosIter = aColumnMapping.begin();
1514 for ( sal_Int32 i = 0; aPosIter != aColumnMapping.end() ; ++aPosIter,++i )
1516 if ( COLUMN_POSITION_NOT_FOUND != aPosIter->second )
1518 if ( sColumns.getLength() )
1519 sColumns.appendAscii(",");
1520 sColumns.append(sQuote);
1521 sColumns.append(aDestColumnNames[aPosIter->second - 1]);
1522 sColumns.append(sQuote);
1525 ::rtl::OUStringBuffer sSql;
1526 sSql.appendAscii("INSERT INTO ");
1527 const ::rtl::OUString sComposedTableName = ::dbtools::composeTableName( xDestMetaData, _xTable, ::dbtools::eInDataManipulation, false, false, true );
1528 sSql.append( sComposedTableName );
1529 sSql.appendAscii(" ( ");
1530 sSql.append( sColumns.makeStringAndClear() );
1531 sSql.appendAscii(" ) ( ");
1532 sSql.append( m_pSourceObject->getSelectStatement());
1533 sSql.appendAscii(" )");
1535 return sSql.makeStringAndClear();
1537 //-------------------------------------------------------------------------
1538 void SAL_CALL CopyTableWizard::initialize( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException)
1540 ::osl::MutexGuard aGuard( m_aMutex );
1541 if ( isInitialized() )
1542 throw AlreadyInitializedException( ::rtl::OUString(), *this );
1544 sal_Int32 nArgCount( _rArguments.getLength() );
1545 if ( ( nArgCount != 2 ) && ( nArgCount != 3 ) )
1546 throw IllegalArgumentException(
1547 String( ModuleRes( STR_CTW_ILLEGAL_PARAMETER_COUNT ) ),
1548 *this,
1554 if ( nArgCount == 3 )
1555 { // ->createWithInteractionHandler
1556 if ( !( _rArguments[2] >>= m_xInteractionHandler ) )
1557 throw IllegalArgumentException(
1558 String(ModuleRes( STR_CTW_ERROR_INVALID_INTERACTIONHANDLER )),
1559 *this,
1563 if ( !m_xInteractionHandler.is() )
1564 m_xInteractionHandler.set( m_aContext.createComponent( "com.sun.star.task.InteractionHandler" ), UNO_QUERY_THROW );
1566 InteractionHandler xSourceDocHandler;
1567 Reference< XPropertySet > xSourceDescriptor( impl_ensureDataAccessDescriptor_throw( _rArguments, 0, m_xSourceConnection, xSourceDocHandler ) );
1568 impl_checkForUnsupportedSettings_throw( xSourceDescriptor );
1569 m_pSourceObject = impl_extractSourceObject_throw( xSourceDescriptor, m_nCommandType );
1570 impl_extractSourceResultSet_throw( xSourceDescriptor );
1572 InteractionHandler xDestDocHandler;
1573 impl_ensureDataAccessDescriptor_throw( _rArguments, 1, m_xDestConnection, xDestDocHandler );
1575 if ( xDestDocHandler.is() && !m_xInteractionHandler.is() )
1576 m_xInteractionHandler = xDestDocHandler;
1578 catch( const RuntimeException& ) { throw; }
1579 catch( const IllegalArgumentException& ) { throw; }
1580 catch( const SQLException& ) { throw; }
1581 catch( const Exception& )
1583 throw WrappedTargetException(
1584 String( ModuleRes( STR_CTW_ERROR_DURING_INITIALIZATION ) ),
1585 *this,
1586 ::cppu::getCaughtException()
1591 //-------------------------------------------------------------------------
1592 ::cppu::IPropertyArrayHelper& CopyTableWizard::getInfoHelper()
1594 return *getArrayHelper();
1597 //------------------------------------------------------------------------------
1598 ::cppu::IPropertyArrayHelper* CopyTableWizard::createArrayHelper( ) const
1600 Sequence< Property > aProps;
1601 describeProperties( aProps );
1602 return new ::cppu::OPropertyArrayHelper( aProps );
1605 //------------------------------------------------------------------------------
1606 Dialog* CopyTableWizard::createDialog( Window* _pParent )
1608 OSL_PRECOND( isInitialized(), "CopyTableWizard::createDialog: not initialized!" );
1609 // this should have been prevented in ::execute already
1611 OCopyTableWizard* pWizard = new OCopyTableWizard(
1612 _pParent,
1613 m_sDestinationTable,
1614 m_nOperation,
1615 *m_pSourceObject,
1616 m_xSourceConnection.getTyped(),
1617 m_xDestConnection.getTyped(),
1618 m_aContext.getLegacyServiceFactory(),
1619 m_xInteractionHandler
1622 impl_attributesToDialog_nothrow( *pWizard );
1624 return pWizard;
1627 //------------------------------------------------------------------------------
1628 void CopyTableWizard::executedDialog( sal_Int16 _nExecutionResult )
1630 CopyTableWizard_DialogBase::executedDialog( _nExecutionResult );
1632 if ( _nExecutionResult == RET_OK )
1633 impl_doCopy_nothrow();
1635 // do this after impl_doCopy_nothrow: The attributes may change during copying, for instance
1636 // if the user entered an unqualified table name
1637 impl_dialogToAttributes_nothrow( impl_getDialog_throw() );
1640 //........................................................................
1641 } // namespace dbaui
1642 //........................................................................
1644 extern "C" void SAL_CALL createRegistryInfo_CopyTableWizard()
1646 static ::dbaui::OMultiInstanceAutoRegistration< ::dbaui::CopyTableWizard > aAutoRegistration;
1649 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */