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 //........................................................................
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 //=========================================================================
150 //=========================================================================
151 typedef ::svt::OGenericUnoDialog CopyTableWizard_DialogBase
;
152 typedef ::cppu::ImplInheritanceHelper1
< CopyTableWizard_DialogBase
154 > CopyTableWizard_Base
;
155 class CopyTableWizard
156 :public CopyTableWizard_Base
157 ,public ::comphelper::OPropertyArrayUsageHelper
< CopyTableWizard
>
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
>& );
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
);
186 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) throw (Exception
, RuntimeException
);
189 virtual Reference
< XPropertySetInfo
> SAL_CALL
getPropertySetInfo() throw(RuntimeException
);
190 virtual ::cppu::IPropertyArrayHelper
& SAL_CALL
getInfoHelper();
192 // OPropertyArrayUsageHelper
193 virtual ::cppu::IPropertyArrayHelper
* createArrayHelper( ) const;
196 ::osl::Mutex
& getMutex() { return m_aMutex
; }
197 bool isInitialized() const { return m_xSourceConnection
.is() && m_pSourceObject
.get() && m_xDestConnection
.is(); }
200 CopyTableWizard( const Reference
< XMultiServiceFactory
>& _rxORB
);
203 // OGenericUnoDialog overridables
204 virtual Dialog
* createDialog( Window
* _pParent
);
205 virtual void executedDialog( sal_Int16 _nExecutionResult
);
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
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
232 the arguments as passed to ->initialize
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
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
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
270 void impl_extractSourceResultSet_throw(
271 const Reference
< XPropertySet
>& i_rDescriptor
274 /** checks whether the given copy source descriptor contains settings which are not
277 Throws an IllegalArgumentException if the descriptor contains a valid setting, which is
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.
301 impl_extractConnection_throw(
302 const Reference
< XPropertySet
>& _rxDataSourceDescriptor
,
303 InteractionHandler
& _out_rxDocInteractionHandler
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.
339 <TRUE/> if and only if copying should be continued.
341 bool impl_processCopyError_nothrow(
342 const CopyTableRowEvent
& _rEvent
);
345 ::comphelper::ComponentContext m_aContext
;
348 sal_Int16 m_nOperation
;
349 ::rtl::OUString m_sDestinationTable
;
350 Optional
< ::rtl::OUString
> m_aPrimaryKeyName
;
351 sal_Bool m_bUseHeaderLineAsColumnNames
;
354 SharedConnection m_xSourceConnection
;
355 sal_Int32 m_nCommandType
;
356 SAL_WNODEPRECATED_DECLARATIONS_PUSH
357 ::std::auto_ptr
< ICopyTableSourceObject
>
359 SAL_WNODEPRECATED_DECLARATIONS_POP
360 Reference
< XResultSet
> m_xSourceResultSet
;
361 Sequence
< Any
> m_aSourceSelection
;
362 sal_Bool m_bSourceSelectionBookmarks
;
365 SharedConnection m_xDestConnection
;
368 InteractionHandler m_xInteractionHandler
;
369 ::cppu::OInterfaceContainerHelper
370 m_aCopyTableListeners
;
371 sal_Int16 m_nOverrideExecutionResult
;
374 //=========================================================================
376 //=========================================================================
377 class CopyTableAccessGuard
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();
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
)
409 ,m_xSourceResultSet()
410 ,m_aSourceSelection()
411 ,m_bSourceSelectionBookmarks( sal_True
)
413 ,m_aCopyTableListeners( m_aMutex
)
414 ,m_nOverrideExecutionResult( -1 )
418 //-------------------------------------------------------------------------
419 CopyTableWizard::~CopyTableWizard()
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
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" ) );
468 //-------------------------------------------------------------------------
469 Reference
< XPropertySetInfo
> SAL_CALL
CopyTableWizard::getPropertySetInfo() throw(RuntimeException
)
471 Reference
< XPropertySetInfo
> xInfo( createPropertySetInfo( getInfoHelper() ) );
475 //--------------------------------------------------------------------
476 ::sal_Int16 SAL_CALL
CopyTableWizard::getOperation() throw (RuntimeException
)
478 CopyTableAccessGuard
aGuard( *this );
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
) ),
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
) ),
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
);
594 throw DisposedException( ::rtl::OUString(), *this );
598 //-------------------------------------------------------------------------
599 const OCopyTableWizard
& CopyTableWizard::impl_getDialog_throw() const
601 const OCopyTableWizard
* pWizard
= dynamic_cast< const OCopyTableWizard
* >( m_pDialog
);
603 throw DisposedException( ::rtl::OUString(), *const_cast< CopyTableWizard
* >( this ) );
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();
624 m_aPrimaryKeyName
.Value
= ::rtl::OUString();
626 m_sDestinationTable
= _rDialog
.getName();
628 m_nOperation
= _rDialog
.getOperation();
629 m_bUseHeaderLineAsColumnNames
= _rDialog
.UseHeaderLine();
632 //-------------------------------------------------------------------------
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
);
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
);
680 xDataSource
= xDataSource
.query( xAsChild
->getParent() );
682 if ( xDataSource
.is() )
683 return lcl_getInteractionHandler_throw( xDataSource
, _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
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
712 _out_rxConnection
= impl_extractConnection_throw( xDescriptor
, _out_rxDocInteractionHandler
);
713 bIsValid
= _out_rxConnection
.is();
718 throw IllegalArgumentException(
719 String( ModuleRes( STR_CTW_INVALID_DATA_ACCESS_DESCRIPTOR
) ),
720 *const_cast< CopyTableWizard
* >( this ),
728 //-------------------------------------------------------------------------
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
];
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(
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." ) ),
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
);
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
);
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
) ) );
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
);
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." ) ),
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
) ),
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() )
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!" );
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() )
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
);
971 xConnection
.set( xDriverManager
->getConnection( sConnectionResource
), UNO_SET_THROW
);
975 if ( xInteractionHandler
!= m_xInteractionHandler
)
976 _out_rxDocInteractionHandler
= xInteractionHandler
;
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
);
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
);
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 ));
1038 //-------------------------------------------------------------------------
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
)
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
] );
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
] );
1073 (m_xDest
.get()->*_pSetter
)( m_rDestPos
, value
);
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
1104 OSL_FAIL( "CopyTableWizard::impl_processCopyError_nothrow: invalid listener response!" );
1105 // ask next listener
1110 catch( const Exception
& )
1112 DBG_UNHANDLED_EXCEPTION();
1115 // no listener felt responsible for the error, or a listener told to ask the user
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
;
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() )
1153 catch( const Exception
& )
1155 DBG_UNHANDLED_EXCEPTION();
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
1216 if ( bSelectedRecordsOnly
)
1218 if ( pSelectedRow
!= pSelEnd
)
1220 if ( m_bSourceSelectionBookmarks
)
1222 bContinue
= xRowLocate
->moveToBookmark( *pSelectedRow
);
1227 OSL_VERIFY( *pSelectedRow
>>= nPos
);
1228 bContinue
= _rxSourceResultSet
->absolute( nPos
);
1234 bContinue
= _rxSourceResultSet
->next();
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();
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
)
1262 // otherwise we don't get the correct value when only the 2nd source column was selected
1266 if ( bAutoIncrement
&& bInsertAutoIncrement
)
1268 xStatementParams
->setInt( 1, nRowCount
);
1269 bInsertAutoIncrement
= sal_False
;
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
,
1282 switch ( aSourceColTypes
[ nSourceColumn
] )
1284 case DataType::DOUBLE
:
1285 case DataType::REAL
:
1286 aTransfer
.transferValue( &XRow::getDouble
, &XParameters::setDouble
);
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
);
1297 case DataType::BIGINT
:
1298 aTransfer
.transferValue( &XRow::getLong
, &XParameters::setLong
);
1301 case DataType::FLOAT
:
1302 aTransfer
.transferValue( &XRow::getFloat
, &XParameters::setFloat
);
1305 case DataType::LONGVARBINARY
:
1306 case DataType::BINARY
:
1307 case DataType::VARBINARY
:
1308 aTransfer
.transferComplexValue( &XRow::getBytes
, &XParameters::setBytes
);
1311 case DataType::DATE
:
1312 aTransfer
.transferComplexValue( &XRow::getDate
, &XParameters::setDate
);
1315 case DataType::TIME
:
1316 aTransfer
.transferComplexValue( &XRow::getTime
, &XParameters::setTime
);
1319 case DataType::TIMESTAMP
:
1320 aTransfer
.transferComplexValue( &XRow::getTimestamp
, &XParameters::setTimestamp
);
1324 if ( aSourcePrec
[nSourceColumn
] > 1 )
1326 aTransfer
.transferComplexValue( &XRow::getBytes
, &XParameters::setBytes
);
1330 case DataType::BOOLEAN
:
1331 aTransfer
.transferValue( &XRow::getBoolean
, &XParameters::setBoolean
);
1334 case DataType::TINYINT
:
1335 aTransfer
.transferValue( &XRow::getByte
, &XParameters::setByte
);
1338 case DataType::SMALLINT
:
1339 aTransfer
.transferValue( &XRow::getShort
, &XParameters::setShort
);
1342 case DataType::INTEGER
:
1343 aTransfer
.transferValue( &XRow::getInt
, &XParameters::setInt
);
1346 case DataType::BLOB
:
1347 aTransfer
.transferComplexValue( &XRow::getBlob
, &XParameters::setBlob
);
1350 case DataType::CLOB
:
1351 aTransfer
.transferComplexValue( &XRow::getClob
, &XParameters::setClob
);
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(
1363 ::dbtools::SQL_INVALID_SQL_DATA_TYPE
,
1370 xStatement
->executeUpdate();
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
);
1385 //-------------------------------------------------------------------------
1386 void CopyTableWizard::impl_doCopy_nothrow()
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();
1406 OSL_FAIL( "CopyTableWizard::impl_doCopy_nothrow: createTable should throw here, shouldn't it?" );
1410 if( CopyTableOperation::CopyDefinitionOnly
== rWizard
.getOperation() )
1415 case CopyTableOperation::AppendData
:
1420 xTable
= rWizard
.createTable();
1423 OSL_FAIL( "CopyTableWizard::impl_doCopy_nothrow: createTable should throw here, shouldn't it?" );
1428 ::utl::SharedUNOComponent
< XPreparedStatement
> xSourceStatement
;
1429 ::utl::SharedUNOComponent
< XResultSet
> xSourceResultSet
;
1431 if ( m_xSourceResultSet
.is() )
1433 xSourceResultSet
.reset( m_xSourceResultSet
, ::utl::SharedUNOComponent
< XResultSet
>::NoTakeOwnership
);
1437 const bool bIsSameConnection
= ( m_xSourceConnection
.getTyped() == m_xDestConnection
.getTyped() );
1438 const bool bIsTable
= ( CommandType::TABLE
== m_nCommandType
);
1440 if ( bIsSameConnection
&& bIsTable
)
1442 // try whether the server supports copying via SQL
1445 m_xDestConnection
->createStatement()->executeUpdate( impl_getServerSideCopyStatement_throw(xTable
) );
1448 catch( const Exception
& )
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
);
1466 case CopyTableOperation::CreateAsView
:
1467 rWizard
.createView();
1471 OSL_FAIL( "CopyTableWizard::impl_doCopy_nothrow: What operation, please?" );
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
) )
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
) ),
1554 if ( nArgCount
== 3 )
1555 { // ->createWithInteractionHandler
1556 if ( !( _rArguments
[2] >>= m_xInteractionHandler
) )
1557 throw IllegalArgumentException(
1558 String(ModuleRes( STR_CTW_ERROR_INVALID_INTERACTIONHANDLER
)),
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
) ),
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(
1613 m_sDestinationTable
,
1616 m_xSourceConnection
.getTyped(),
1617 m_xDestConnection
.getTyped(),
1618 m_aContext
.getLegacyServiceFactory(),
1619 m_xInteractionHandler
1622 impl_attributesToDialog_nothrow( *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: */