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