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/sdbcx/XRowLocate.hpp>
52 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
53 #include <com/sun/star/sdb/SQLContext.hpp>
54 #include <com/sun/star/sdbc/DriverManager.hpp>
55 #include <com/sun/star/sdbc/ConnectionPool.hpp>
57 #include <comphelper/processfactory.hxx>
58 #include <comphelper/interaction.hxx>
59 #include <comphelper/namedvaluecollection.hxx>
60 #include <comphelper/proparrhlp.hxx>
61 #include <connectivity/dbexception.hxx>
62 #include <connectivity/dbtools.hxx>
63 #include <cppuhelper/exc_hlp.hxx>
64 #include <cppuhelper/implbase.hxx>
65 #include <comphelper/interfacecontainer2.hxx>
66 #include <rtl/ustrbuf.hxx>
67 #include <svtools/genericunodialog.hxx>
68 #include <tools/diagnose_ex.h>
69 #include <unotools/sharedunocomponent.hxx>
70 #include <vcl/msgbox.hxx>
71 #include <vcl/waitobj.hxx>
76 using ::com::sun::star::uno::Reference
;
77 using ::com::sun::star::uno::XInterface
;
78 using ::com::sun::star::uno::UNO_QUERY
;
79 using ::com::sun::star::uno::UNO_QUERY_THROW
;
80 using ::com::sun::star::uno::UNO_SET_THROW
;
81 using ::com::sun::star::uno::Exception
;
82 using ::com::sun::star::uno::RuntimeException
;
83 using ::com::sun::star::uno::Any
;
84 using ::com::sun::star::uno::makeAny
;
85 using ::com::sun::star::uno::Sequence
;
86 using ::com::sun::star::uno::XComponentContext
;
87 using ::com::sun::star::beans::XPropertySetInfo
;
88 using ::com::sun::star::lang::XMultiServiceFactory
;
89 using ::com::sun::star::beans::Property
;
90 using ::com::sun::star::sdb::application::XCopyTableWizard
;
91 using ::com::sun::star::sdb::application::XCopyTableListener
;
92 using ::com::sun::star::sdb::application::CopyTableRowEvent
;
93 using ::com::sun::star::beans::Optional
;
94 using ::com::sun::star::lang::IllegalArgumentException
;
95 using ::com::sun::star::ucb::AlreadyInitializedException
;
96 using ::com::sun::star::beans::XPropertySet
;
97 using ::com::sun::star::lang::NotInitializedException
;
98 using ::com::sun::star::lang::XServiceInfo
;
99 using ::com::sun::star::sdbc::XConnection
;
100 using ::com::sun::star::sdbc::XDataSource
;
101 using ::com::sun::star::container::XNameAccess
;
102 using ::com::sun::star::container::XChild
;
103 using ::com::sun::star::task::InteractionHandler
;
104 using ::com::sun::star::task::XInteractionHandler
;
105 using ::com::sun::star::frame::XModel
;
106 using ::com::sun::star::sdb::DatabaseContext
;
107 using ::com::sun::star::sdb::XDatabaseContext
;
108 using ::com::sun::star::sdb::XDocumentDataSource
;
109 using ::com::sun::star::sdb::XCompletedConnection
;
110 using ::com::sun::star::lang::WrappedTargetException
;
111 using ::com::sun::star::sdbcx::XTablesSupplier
;
112 using ::com::sun::star::sdb::XQueriesSupplier
;
113 using ::com::sun::star::lang::DisposedException
;
114 using ::com::sun::star::sdbc::XPreparedStatement
;
115 using ::com::sun::star::sdb::XSingleSelectQueryComposer
;
116 using ::com::sun::star::sdbc::XDatabaseMetaData
;
117 using ::com::sun::star::sdbcx::XColumnsSupplier
;
118 using ::com::sun::star::sdbc::XParameters
;
119 using ::com::sun::star::sdbc::XResultSet
;
120 using ::com::sun::star::sdbc::XRow
;
121 using ::com::sun::star::sdbcx::XRowLocate
;
122 using ::com::sun::star::sdbc::XResultSetMetaDataSupplier
;
123 using ::com::sun::star::sdbc::XResultSetMetaData
;
124 using ::com::sun::star::sdbc::SQLException
;
125 using ::com::sun::star::sdb::SQLContext
;
126 using ::com::sun::star::sdbc::ConnectionPool
;
127 using ::com::sun::star::sdbc::XDriverManager
;
128 using ::com::sun::star::sdbc::DriverManager
;
129 using ::com::sun::star::beans::PropertyValue
;
131 namespace CopyTableOperation
= ::com::sun::star::sdb::application::CopyTableOperation
;
132 namespace CopyTableContinuation
= ::com::sun::star::sdb::application::CopyTableContinuation
;
133 namespace CommandType
= ::com::sun::star::sdb::CommandType
;
134 namespace DataType
= ::com::sun::star::sdbc::DataType
;
136 typedef ::utl::SharedUNOComponent
< XConnection
> SharedConnection
;
139 typedef ::svt::OGenericUnoDialog CopyTableWizard_DialogBase
;
140 typedef ::cppu::ImplInheritanceHelper
< CopyTableWizard_DialogBase
142 > CopyTableWizard_Base
;
143 class CopyTableWizard
144 :public CopyTableWizard_Base
145 ,public ::comphelper::OPropertyArrayUsageHelper
< CopyTableWizard
>
149 virtual OUString SAL_CALL
getImplementationName() throw(RuntimeException
, std::exception
) override
;
150 virtual css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() throw(RuntimeException
, std::exception
) override
;
152 // XServiceInfo - static methods
153 /// @throws RuntimeException
154 static Sequence
< OUString
> getSupportedServiceNames_Static() throw( RuntimeException
);
155 /// @throws RuntimeException
156 static OUString
getImplementationName_Static() throw( RuntimeException
);
157 static Reference
< XInterface
> Create( const Reference
< XMultiServiceFactory
>& );
160 virtual ::sal_Int16 SAL_CALL
getOperation() throw (RuntimeException
, std::exception
) override
;
161 virtual void SAL_CALL
setOperation( ::sal_Int16 _operation
) throw (IllegalArgumentException
, RuntimeException
, std::exception
) override
;
162 virtual OUString SAL_CALL
getDestinationTableName() throw (RuntimeException
, std::exception
) override
;
163 virtual void SAL_CALL
setDestinationTableName( const OUString
& _destinationTableName
) throw (RuntimeException
, std::exception
) override
;
164 virtual Optional
< OUString
> SAL_CALL
getCreatePrimaryKey() throw (RuntimeException
, std::exception
) override
;
165 virtual void SAL_CALL
setCreatePrimaryKey( const Optional
< OUString
>& _newPrimaryKey
) throw (IllegalArgumentException
, SQLException
, RuntimeException
, std::exception
) override
;
166 virtual sal_Bool SAL_CALL
getUseHeaderLineAsColumnNames() throw (RuntimeException
, std::exception
) override
;
167 virtual void SAL_CALL
setUseHeaderLineAsColumnNames( sal_Bool _bUseHeaderLineAsColumnNames
) throw (RuntimeException
, std::exception
) override
;
168 virtual void SAL_CALL
addCopyTableListener( const Reference
< XCopyTableListener
>& Listener
) throw (RuntimeException
, std::exception
) override
;
169 virtual void SAL_CALL
removeCopyTableListener( const Reference
< XCopyTableListener
>& Listener
) throw (RuntimeException
, std::exception
) override
;
171 // XCopyTableWizard::XExecutableDialog
172 virtual void SAL_CALL
setTitle( const OUString
& aTitle
) throw (RuntimeException
, std::exception
) override
;
173 virtual ::sal_Int16 SAL_CALL
execute( ) throw (RuntimeException
, std::exception
) override
;
176 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) throw (Exception
, RuntimeException
, std::exception
) override
;
179 virtual Reference
< XPropertySetInfo
> SAL_CALL
getPropertySetInfo() throw(RuntimeException
, std::exception
) override
;
180 virtual ::cppu::IPropertyArrayHelper
& SAL_CALL
getInfoHelper() override
;
182 // OPropertyArrayUsageHelper
183 virtual ::cppu::IPropertyArrayHelper
* createArrayHelper( ) const override
;
186 ::osl::Mutex
& getMutex() { return m_aMutex
; }
187 bool isInitialized() const { return m_xSourceConnection
.is() && m_pSourceObject
.get() && m_xDestConnection
.is(); }
190 explicit CopyTableWizard( const Reference
< XComponentContext
>& _rxORB
);
191 virtual ~CopyTableWizard() override
;
193 // OGenericUnoDialog overridables
194 virtual VclPtr
<Dialog
> createDialog( vcl::Window
* _pParent
) override
;
195 virtual void executedDialog( sal_Int16 _nExecutionResult
) override
;
198 /// ensures our current attribute values are reflected in the dialog
199 void impl_attributesToDialog_nothrow( OCopyTableWizard
& _rDialog
) const;
201 /// ensures the current dialog settings are reflected in our attributes
202 void impl_dialogToAttributes_nothrow( const OCopyTableWizard
& _rDialog
);
204 /** returns our typed dialog
206 @throws css::uno::RuntimeException
207 if we don't have a dialog at the moment the method is called
210 impl_getDialog_throw();
212 /** ensures the given argument sequence contains a valid data access descriptor at the given position
214 the arguments as passed to ->initialize
216 the position within ->_rAllArgs which contains the data access descriptor
217 @param _out_rxConnection
218 will, upon successful return, contain the connection for the data source
219 @param _out_rxDocInteractionHandler
220 will, upon successful return, contain the interaction handler which could
221 be deduced from database document described by the descriptor, if any.
222 (It is possible that the descriptor does not allow to deduce a database document,
223 in which case <code>_out_rxDocInteractionHandler</code> will be <NULL/>.)
224 @return the data access descriptor
226 Reference
< XPropertySet
>
227 impl_ensureDataAccessDescriptor_throw(
228 const Sequence
< Any
>& _rAllArgs
,
229 const sal_Int16 _nArgPos
,
230 SharedConnection
& _out_rxConnection
,
231 Reference
< XInteractionHandler
>& _out_rxDocInteractionHandler
234 /** extracts the source object (table or query) described by the given descriptor,
235 relative to m_xSourceConnection
237 ::std::unique_ptr
< ICopyTableSourceObject
>
238 impl_extractSourceObject_throw(
239 const Reference
< XPropertySet
>& _rxDescriptor
,
240 sal_Int32
& _out_rCommandType
243 /** extracts the result set to copy records from, and the selection-related aspects, if any.
245 Effectively, this method extracts m_xSourceResultSet, m_aSourceSelection, and m_bSourceSelectionBookmarks.
247 If an inconsistent/insufficient sub set of those properties is present in the descriptor, and exception
250 void impl_extractSourceResultSet_throw(
251 const Reference
< XPropertySet
>& i_rDescriptor
254 /** checks whether the given copy source descriptor contains settings which are not
257 Throws an IllegalArgumentException if the descriptor contains a valid setting, which is
260 void impl_checkForUnsupportedSettings_throw(
261 const Reference
< XPropertySet
>& _rxSourceDescriptor
) const;
263 /** obtaines the connection described by the given data access descriptor
265 If needed and possible, the method will ask the user, using the interaction
266 handler associated with the database described by the descriptor.
268 All errors are handled with the InteractionHandler associated with the data source,
269 if there is one. Else, they will be silenced (but asserted in non-product builds).
271 @param _rxDataSourceDescriptor
272 the data access descriptor describing the data source whose connection
273 should be obtained. Must not be <NULL/>.
274 @param _out_rxDocInteractionHandler
275 the interaction handler which could be deduced from the descriptor
277 @throws RuntimeException
278 if anything goes seriously wrong.
281 impl_extractConnection_throw(
282 const Reference
< XPropertySet
>& _rxDataSourceDescriptor
,
283 Reference
< XInteractionHandler
>& _out_rxDocInteractionHandler
286 /** actually copies the table
288 This method is called after the dialog has been successfully executed.
290 void impl_doCopy_nothrow();
292 /** creates the INSERT INTO statement
293 @param _xTable The destination table.
295 OUString
impl_getServerSideCopyStatement_throw( const Reference
< XPropertySet
>& _xTable
);
297 /** creates the statement which, when executed, will produce the source data to copy
299 If the source object refers to a query which contains parameters, those parameters
300 are filled in, using an interaction handler.
302 ::utl::SharedUNOComponent
< XPreparedStatement
>
303 impl_createSourceStatement_throw() const;
305 /** copies the data rows from the given source result set to the given destination table
307 void impl_copyRows_throw(
308 const Reference
< XResultSet
>& _rxSourceResultSet
,
309 const Reference
< XPropertySet
>& _rxDestTable
312 /** processes an error which occurred during copying
314 First, all listeners are ask. If a listener tells to cancel or continue copying, this is reported to the
315 method's caller. If a listener tells to ask the user, this is done, and the user's decision is
316 reported to the method's caller.
319 <TRUE/> if and only if copying should be continued.
321 bool impl_processCopyError_nothrow(
322 const CopyTableRowEvent
& _rEvent
);
325 Reference
<XComponentContext
> m_xContext
;
328 sal_Int16 m_nOperation
;
329 OUString m_sDestinationTable
;
330 Optional
< OUString
> m_aPrimaryKeyName
;
331 bool m_bUseHeaderLineAsColumnNames
;
334 SharedConnection m_xSourceConnection
;
335 sal_Int32 m_nCommandType
;
336 ::std::unique_ptr
< ICopyTableSourceObject
>
338 Reference
< XResultSet
> m_xSourceResultSet
;
339 Sequence
< Any
> m_aSourceSelection
;
340 bool m_bSourceSelectionBookmarks
;
343 SharedConnection m_xDestConnection
;
346 Reference
< XInteractionHandler
> m_xInteractionHandler
;
347 ::comphelper::OInterfaceContainerHelper2
348 m_aCopyTableListeners
;
349 sal_Int16 m_nOverrideExecutionResult
;
353 class CopyTableAccessGuard
356 explicit CopyTableAccessGuard( CopyTableWizard
& _rWizard
)
357 :m_rWizard( _rWizard
)
359 m_rWizard
.getMutex().acquire();
360 if ( !m_rWizard
.isInitialized() )
361 throw NotInitializedException();
364 ~CopyTableAccessGuard()
366 m_rWizard
.getMutex().release();
370 CopyTableWizard
& m_rWizard
;
373 CopyTableWizard::CopyTableWizard( const Reference
< XComponentContext
>& _rxORB
)
374 :CopyTableWizard_Base( _rxORB
)
375 ,m_xContext( _rxORB
)
376 ,m_nOperation( CopyTableOperation::CopyDefinitionAndData
)
377 ,m_sDestinationTable()
378 ,m_aPrimaryKeyName( false, "ID" )
379 ,m_bUseHeaderLineAsColumnNames( true )
380 ,m_xSourceConnection()
381 ,m_nCommandType( CommandType::COMMAND
)
383 ,m_xSourceResultSet()
384 ,m_aSourceSelection()
385 ,m_bSourceSelectionBookmarks( true )
387 ,m_aCopyTableListeners( m_aMutex
)
388 ,m_nOverrideExecutionResult( -1 )
392 CopyTableWizard::~CopyTableWizard()
396 // protect some members whose dtor might potentially throw
397 try { m_xSourceConnection
.clear(); }
398 catch( const Exception
& ) { DBG_UNHANDLED_EXCEPTION(); }
399 try { m_xDestConnection
.clear(); }
400 catch( const Exception
& ) { DBG_UNHANDLED_EXCEPTION(); }
402 // TODO: shouldn't we have explicit disposal support? If a listener is registered
403 // at our instance, and perhaps holds this our instance by a hard ref, then we'll never
405 // However, adding XComponent support to the GenericUNODialog probably requires
406 // some thinking - would it break existing clients which do not call a dispose, then?
409 Reference
< XInterface
> CopyTableWizard::Create( const Reference
< XMultiServiceFactory
>& _rxFactory
)
411 return *( new CopyTableWizard( comphelper::getComponentContext(_rxFactory
) ) );
414 OUString SAL_CALL
CopyTableWizard::getImplementationName() throw(RuntimeException
, std::exception
)
416 return getImplementationName_Static();
419 OUString
CopyTableWizard::getImplementationName_Static() throw(RuntimeException
)
421 return OUString( "org.openoffice.comp.dbu.CopyTableWizard" );
424 css::uno::Sequence
<OUString
> SAL_CALL
CopyTableWizard::getSupportedServiceNames() throw(RuntimeException
, std::exception
)
426 return getSupportedServiceNames_Static();
429 css::uno::Sequence
<OUString
> CopyTableWizard::getSupportedServiceNames_Static() throw(RuntimeException
)
431 css::uno::Sequence
<OUString
> aSupported
{ "com.sun.star.sdb.application.CopyTableWizard" };
435 Reference
< XPropertySetInfo
> SAL_CALL
CopyTableWizard::getPropertySetInfo() throw(RuntimeException
, std::exception
)
437 Reference
< XPropertySetInfo
> xInfo( createPropertySetInfo( getInfoHelper() ) );
441 ::sal_Int16 SAL_CALL
CopyTableWizard::getOperation() throw (RuntimeException
, std::exception
)
443 CopyTableAccessGuard
aGuard( *this );
447 void SAL_CALL
CopyTableWizard::setOperation( ::sal_Int16 _operation
) throw (IllegalArgumentException
, RuntimeException
, std::exception
)
449 CopyTableAccessGuard
aGuard( *this );
451 if ( ( _operation
!= CopyTableOperation::CopyDefinitionAndData
)
452 && ( _operation
!= CopyTableOperation::CopyDefinitionOnly
)
453 && ( _operation
!= CopyTableOperation::CreateAsView
)
454 && ( _operation
!= CopyTableOperation::AppendData
)
456 throw IllegalArgumentException( OUString(), *this, 1 );
458 if ( ( _operation
== CopyTableOperation::CreateAsView
)
459 && !OCopyTableWizard::supportsViews( m_xDestConnection
)
461 throw IllegalArgumentException(
462 OUString( ModuleRes( STR_CTW_NO_VIEWS_SUPPORT
) ),
467 m_nOperation
= _operation
;
470 OUString SAL_CALL
CopyTableWizard::getDestinationTableName() throw (RuntimeException
, std::exception
)
472 CopyTableAccessGuard
aGuard( *this );
473 return m_sDestinationTable
;
476 void SAL_CALL
CopyTableWizard::setDestinationTableName( const OUString
& _destinationTableName
) throw (RuntimeException
, std::exception
)
478 CopyTableAccessGuard
aGuard( *this );
479 m_sDestinationTable
= _destinationTableName
;
482 Optional
< OUString
> SAL_CALL
CopyTableWizard::getCreatePrimaryKey() throw (RuntimeException
, std::exception
)
484 CopyTableAccessGuard
aGuard( *this );
485 return m_aPrimaryKeyName
;
488 void SAL_CALL
CopyTableWizard::setCreatePrimaryKey( const Optional
< OUString
>& _newPrimaryKey
) throw (IllegalArgumentException
, SQLException
, RuntimeException
, std::exception
)
490 CopyTableAccessGuard
aGuard( *this );
492 if ( _newPrimaryKey
.IsPresent
&& !OCopyTableWizard::supportsPrimaryKey( m_xDestConnection
) )
493 throw IllegalArgumentException(
494 OUString( ModuleRes( STR_CTW_NO_PRIMARY_KEY_SUPPORT
) ),
499 m_aPrimaryKeyName
= _newPrimaryKey
;
502 sal_Bool SAL_CALL
CopyTableWizard::getUseHeaderLineAsColumnNames() throw (RuntimeException
, std::exception
)
504 CopyTableAccessGuard
aGuard( *this );
505 return m_bUseHeaderLineAsColumnNames
;
508 void SAL_CALL
CopyTableWizard::setUseHeaderLineAsColumnNames( sal_Bool _bUseHeaderLineAsColumnNames
) throw (RuntimeException
, std::exception
)
510 CopyTableAccessGuard
aGuard( *this );
511 m_bUseHeaderLineAsColumnNames
= _bUseHeaderLineAsColumnNames
;
514 void SAL_CALL
CopyTableWizard::addCopyTableListener( const Reference
< XCopyTableListener
>& _rxListener
) throw (RuntimeException
, std::exception
)
516 CopyTableAccessGuard
aGuard( *this );
517 if ( _rxListener
.is() )
518 m_aCopyTableListeners
.addInterface( _rxListener
);
521 void SAL_CALL
CopyTableWizard::removeCopyTableListener( const Reference
< XCopyTableListener
>& _rxListener
) throw (RuntimeException
, std::exception
)
523 CopyTableAccessGuard
aGuard( *this );
524 if ( _rxListener
.is() )
525 m_aCopyTableListeners
.removeInterface( _rxListener
);
528 void SAL_CALL
CopyTableWizard::setTitle( const OUString
& _rTitle
) throw (RuntimeException
, std::exception
)
530 CopyTableAccessGuard
aGuard( *this );
531 CopyTableWizard_DialogBase::setTitle( _rTitle
);
534 ::sal_Int16 SAL_CALL
CopyTableWizard::execute( ) throw (RuntimeException
, std::exception
)
536 CopyTableAccessGuard
aGuard( *this );
538 m_nOverrideExecutionResult
= -1;
539 sal_Int16 nExecutionResult
= CopyTableWizard_DialogBase::execute();
540 if ( m_nOverrideExecutionResult
)
541 nExecutionResult
= m_nOverrideExecutionResult
;
543 return nExecutionResult
;
546 OCopyTableWizard
& CopyTableWizard::impl_getDialog_throw()
548 OCopyTableWizard
* pWizard
= dynamic_cast< OCopyTableWizard
* >( m_pDialog
.get() );
550 throw DisposedException( OUString(), *this );
554 void CopyTableWizard::impl_attributesToDialog_nothrow( OCopyTableWizard
& _rDialog
) const
556 // primary key column
557 _rDialog
.setCreatePrimaryKey( m_aPrimaryKeyName
.IsPresent
, m_aPrimaryKeyName
.Value
);
558 _rDialog
.setUseHeaderLine(m_bUseHeaderLineAsColumnNames
);
560 // everything else was passed at construction time already
563 void CopyTableWizard::impl_dialogToAttributes_nothrow( const OCopyTableWizard
& _rDialog
)
565 m_aPrimaryKeyName
.IsPresent
= _rDialog
.shouldCreatePrimaryKey();
566 if ( m_aPrimaryKeyName
.IsPresent
)
567 m_aPrimaryKeyName
.Value
= _rDialog
.getPrimaryKeyName();
569 m_aPrimaryKeyName
.Value
.clear();
571 m_sDestinationTable
= _rDialog
.getName();
573 m_nOperation
= _rDialog
.getOperation();
574 m_bUseHeaderLineAsColumnNames
= _rDialog
.UseHeaderLine();
579 /** tries to obtain the InteractionHandler associated with a given data source
581 If the data source is a sdb-level data source, it will have a DatabaseDocument associated
582 with it. This document may have an InteractionHandler used while loading it.
584 @throws RuntimeException
585 if it occurs during invoking any of the data source's methods, or if any of the involved
586 components violates its contract by not providing the required interfaces
588 Reference
< XInteractionHandler
> lcl_getInteractionHandler_throw( const Reference
< XDataSource
>& _rxDataSource
, const Reference
< XInteractionHandler
>& _rFallback
)
590 Reference
< XInteractionHandler
> xHandler( _rFallback
);
592 // try to obtain the document model
593 Reference
< XModel
> xDocumentModel
;
594 Reference
< XDocumentDataSource
> xDocDataSource( _rxDataSource
, UNO_QUERY
);
595 if ( xDocDataSource
.is() )
596 xDocumentModel
.set( xDocDataSource
->getDatabaseDocument(), UNO_QUERY_THROW
);
598 // see whether the document model can provide a handler
599 if ( xDocumentModel
.is() )
601 ::comphelper::NamedValueCollection
aModelArgs( xDocumentModel
->getArgs() );
602 xHandler
= aModelArgs
.getOrDefault( "InteractionHandler", xHandler
);
607 /** tries to obtain the InteractionHandler associated with a given connection
609 If the connection belongs to a sdb-level data source, then this data source
610 is examined for an interaction handler. Else, <NULL/> is returned.
612 @throws RuntimeException
613 if it occurs during invoking any of the data source's methods, or if any of the involved
614 components violates its contract by not providing the required interfaces
616 Reference
< XInteractionHandler
> lcl_getInteractionHandler_throw( const Reference
< XConnection
>& _rxConnection
, const Reference
< XInteractionHandler
>& _rFallback
)
618 // try whether there is a data source which the connection belongs to
619 Reference
< XDataSource
> xDataSource
;
620 Reference
< XChild
> xAsChild( _rxConnection
, UNO_QUERY
);
622 xDataSource
.set(xAsChild
->getParent(), css::uno::UNO_QUERY
);
624 if ( xDataSource
.is() )
625 return lcl_getInteractionHandler_throw( xDataSource
, _rFallback
);
631 Reference
< XPropertySet
> CopyTableWizard::impl_ensureDataAccessDescriptor_throw(
632 const Sequence
< Any
>& _rAllArgs
, const sal_Int16 _nArgPos
, SharedConnection
& _out_rxConnection
,
633 Reference
< XInteractionHandler
>& _out_rxDocInteractionHandler
) const
635 Reference
< XPropertySet
> xDescriptor
;
636 _rAllArgs
[ _nArgPos
] >>= xDescriptor
;
638 // the descriptor must be non-NULL, of course
639 bool bIsValid
= xDescriptor
.is();
641 // it must support the proper service
644 Reference
< XServiceInfo
> xSI( xDescriptor
, UNO_QUERY
);
645 bIsValid
= ( xSI
.is()
646 && xSI
->supportsService( "com.sun.star.sdb.DataAccessDescriptor" ) );
649 // it must be able to provide a connection
652 _out_rxConnection
= impl_extractConnection_throw( xDescriptor
, _out_rxDocInteractionHandler
);
653 bIsValid
= _out_rxConnection
.is();
658 throw IllegalArgumentException(
659 OUString( ModuleRes( STR_CTW_INVALID_DATA_ACCESS_DESCRIPTOR
) ),
660 *const_cast< CopyTableWizard
* >( this ),
670 bool lcl_hasNonEmptyStringValue_throw( const Reference
< XPropertySet
>& _rxDescriptor
,
671 const Reference
< XPropertySetInfo
>& rxPSI
, const OUString
& _rPropertyName
)
674 if ( rxPSI
->hasPropertyByName( _rPropertyName
) )
676 OSL_VERIFY( _rxDescriptor
->getPropertyValue( _rPropertyName
) >>= sValue
);
678 return !sValue
.isEmpty();
682 void CopyTableWizard::impl_checkForUnsupportedSettings_throw( const Reference
< XPropertySet
>& _rxSourceDescriptor
) const
684 OSL_PRECOND( _rxSourceDescriptor
.is(), "CopyTableWizard::impl_checkForUnsupportedSettings_throw: illegal argument!" );
685 Reference
< XPropertySetInfo
> xPSI( _rxSourceDescriptor
->getPropertySetInfo(), UNO_SET_THROW
);
686 OUString sUnsupportedSetting
;
688 const OUString aSettings
[] = {
689 OUString(PROPERTY_FILTER
), OUString(PROPERTY_ORDER
), OUString(PROPERTY_HAVING_CLAUSE
), OUString(PROPERTY_GROUP_BY
)
691 for (const auto & aSetting
: aSettings
)
693 if ( lcl_hasNonEmptyStringValue_throw( _rxSourceDescriptor
, xPSI
, aSetting
) )
695 sUnsupportedSetting
= aSetting
;
700 if ( !sUnsupportedSetting
.isEmpty() )
703 OUString(ModuleRes(STR_CTW_ERROR_UNSUPPORTED_SETTING
)).
704 replaceFirst("$name$", sUnsupportedSetting
));
705 throw IllegalArgumentException(
707 *const_cast< CopyTableWizard
* >( this ),
714 ::std::unique_ptr
< ICopyTableSourceObject
> CopyTableWizard::impl_extractSourceObject_throw( const Reference
< XPropertySet
>& _rxDescriptor
, sal_Int32
& _out_rCommandType
) const
716 OSL_PRECOND( _rxDescriptor
.is() && m_xSourceConnection
.is(), "CopyTableWizard::impl_extractSourceObject_throw: illegal arguments!" );
718 Reference
< XPropertySetInfo
> xPSI( _rxDescriptor
->getPropertySetInfo(), UNO_SET_THROW
);
719 if ( !xPSI
->hasPropertyByName( PROPERTY_COMMAND
)
720 || !xPSI
->hasPropertyByName( PROPERTY_COMMAND_TYPE
)
722 throw IllegalArgumentException("Expecting a table or query specification.",
724 *const_cast< CopyTableWizard
* >( this ), 1);
727 _out_rCommandType
= CommandType::COMMAND
;
728 OSL_VERIFY( _rxDescriptor
->getPropertyValue( PROPERTY_COMMAND
) >>= sCommand
);
729 OSL_VERIFY( _rxDescriptor
->getPropertyValue( PROPERTY_COMMAND_TYPE
) >>= _out_rCommandType
);
731 ::std::unique_ptr
< ICopyTableSourceObject
> pSourceObject
;
732 Reference
< XNameAccess
> xContainer
;
733 switch ( _out_rCommandType
)
735 case CommandType::TABLE
:
737 Reference
< XTablesSupplier
> xSuppTables( m_xSourceConnection
.getTyped(), UNO_QUERY
);
738 if ( xSuppTables
.is() )
739 xContainer
.set( xSuppTables
->getTables(), UNO_SET_THROW
);
742 case CommandType::QUERY
:
744 Reference
< XQueriesSupplier
> xSuppQueries( m_xSourceConnection
.getTyped(), UNO_QUERY
);
745 if ( xSuppQueries
.is() )
746 xContainer
.set( xSuppQueries
->getQueries(), UNO_SET_THROW
);
750 throw IllegalArgumentException(
751 OUString( ModuleRes( STR_CTW_ONLY_TABLES_AND_QUERIES_SUPPORT
) ),
752 *const_cast< CopyTableWizard
* >( this ),
757 if ( xContainer
.is() )
759 pSourceObject
.reset( new ObjectCopySource( m_xSourceConnection
,
760 Reference
< XPropertySet
>( xContainer
->getByName( sCommand
), UNO_QUERY_THROW
) ) );
764 // our source connection is an SDBC level connection only, not a SDBCX level one
765 // Which means it cannot provide the to-be-copied object as component.
767 if ( _out_rCommandType
== CommandType::QUERY
)
768 // we cannot copy a query if the connection cannot provide it ...
769 throw IllegalArgumentException(
770 OUString(ModuleRes( STR_CTW_ERROR_NO_QUERY
)),
771 *const_cast< CopyTableWizard
* >( this ),
774 pSourceObject
.reset( new NamedTableCopySource( m_xSourceConnection
, sCommand
) );
777 return pSourceObject
;
780 void CopyTableWizard::impl_extractSourceResultSet_throw( const Reference
< XPropertySet
>& i_rDescriptor
)
782 Reference
< XPropertySetInfo
> xPSI( i_rDescriptor
->getPropertySetInfo(), UNO_SET_THROW
);
784 // extract relevant settings
785 if ( xPSI
->hasPropertyByName( PROPERTY_RESULT_SET
) )
786 m_xSourceResultSet
.set( i_rDescriptor
->getPropertyValue( PROPERTY_RESULT_SET
), UNO_QUERY
);
788 if ( xPSI
->hasPropertyByName( PROPERTY_SELECTION
) )
789 OSL_VERIFY( i_rDescriptor
->getPropertyValue( PROPERTY_SELECTION
) >>= m_aSourceSelection
);
791 if ( xPSI
->hasPropertyByName( PROPERTY_BOOKMARK_SELECTION
) )
792 OSL_VERIFY( i_rDescriptor
->getPropertyValue( PROPERTY_BOOKMARK_SELECTION
) >>= m_bSourceSelectionBookmarks
);
795 const bool bHasResultSet
= m_xSourceResultSet
.is();
796 const bool bHasSelection
= ( m_aSourceSelection
.getLength() != 0 );
797 if ( bHasSelection
&& !bHasResultSet
)
798 throw IllegalArgumentException("A result set is needed when specifying a selection to copy.",
802 if ( bHasSelection
&& m_bSourceSelectionBookmarks
)
804 Reference
< XRowLocate
> xRowLocate( m_xSourceResultSet
, UNO_QUERY
);
805 if ( !xRowLocate
.is() )
807 ::dbtools::throwGenericSQLException(
808 OUString( ModuleRes( STR_CTW_COPY_SOURCE_NEEDS_BOOKMARKS
) ),
815 SharedConnection
CopyTableWizard::impl_extractConnection_throw( const Reference
< XPropertySet
>& _rxDataSourceDescriptor
,
816 Reference
< XInteractionHandler
>& _out_rxDocInteractionHandler
) const
818 SharedConnection xConnection
;
820 OSL_PRECOND( _rxDataSourceDescriptor
.is(), "CopyTableWizard::impl_extractConnection_throw: no descriptor!" );
821 if ( !_rxDataSourceDescriptor
.is() )
824 Reference
< XInteractionHandler
> xInteractionHandler
;
828 Reference
< XPropertySetInfo
> xPSI( _rxDataSourceDescriptor
->getPropertySetInfo(), UNO_SET_THROW
);
830 // if there's an ActiveConnection, use it
831 if ( xPSI
->hasPropertyByName( PROPERTY_ACTIVE_CONNECTION
) )
833 Reference
< XConnection
> xPure
;
834 OSL_VERIFY( _rxDataSourceDescriptor
->getPropertyValue( PROPERTY_ACTIVE_CONNECTION
) >>= xPure
);
835 xConnection
.reset( xPure
, SharedConnection::NoTakeOwnership
);
837 if ( xConnection
.is() )
839 xInteractionHandler
= lcl_getInteractionHandler_throw( xConnection
.getTyped(), m_xInteractionHandler
);
840 SAL_WARN_IF( !xInteractionHandler
.is(), "dbaccess.ui", "CopyTableWizard::impl_extractConnection_throw: lcl_getInteractionHandler_throw returned nonsense!" );
844 // there could be a DataSourceName or a DatabaseLocation, describing the css.sdb.DataSource
845 OUString sDataSource
, sDatabaseLocation
;
846 if ( xPSI
->hasPropertyByName( PROPERTY_DATASOURCENAME
) )
847 OSL_VERIFY( _rxDataSourceDescriptor
->getPropertyValue( PROPERTY_DATASOURCENAME
) >>= sDataSource
);
848 if ( xPSI
->hasPropertyByName( PROPERTY_DATABASE_LOCATION
) )
849 OSL_VERIFY( _rxDataSourceDescriptor
->getPropertyValue( PROPERTY_DATABASE_LOCATION
) >>= sDatabaseLocation
);
851 // need a DatabaseContext for loading the data source
852 Reference
< XDatabaseContext
> xDatabaseContext
= DatabaseContext::create( m_xContext
);
853 Reference
< XDataSource
> xDataSource
;
854 if ( !sDataSource
.isEmpty() )
855 xDataSource
.set( xDatabaseContext
->getByName( sDataSource
), UNO_QUERY_THROW
);
856 if ( !xDataSource
.is() && !sDatabaseLocation
.isEmpty() )
857 xDataSource
.set( xDatabaseContext
->getByName( sDatabaseLocation
), UNO_QUERY_THROW
);
859 if ( xDataSource
.is() )
861 // first, try connecting with completion
862 xInteractionHandler
= lcl_getInteractionHandler_throw( xDataSource
, m_xInteractionHandler
);
863 SAL_WARN_IF( !xInteractionHandler
.is(), "dbaccess.ui", "CopyTableWizard::impl_extractConnection_throw: lcl_getInteractionHandler_throw returned nonsense!" );
864 if ( xInteractionHandler
.is() )
866 Reference
< XCompletedConnection
> xInteractiveConnection( xDataSource
, UNO_QUERY
);
867 if ( xInteractiveConnection
.is() )
868 xConnection
.reset( xInteractiveConnection
->connectWithCompletion( xInteractionHandler
), SharedConnection::TakeOwnership
);
871 // interactively connecting was not successful or possible -> connect without interaction
872 if ( !xConnection
.is() )
874 xConnection
.reset( xDataSource
->getConnection( OUString(), OUString() ), SharedConnection::TakeOwnership
);
878 if ( xConnection
.is() )
881 // finally, there could be a ConnectionResource/ConnectionInfo
882 OUString sConnectionResource
;
883 Sequence
< PropertyValue
> aConnectionInfo
;
884 if ( xPSI
->hasPropertyByName( PROPERTY_CONNECTION_RESOURCE
) )
885 OSL_VERIFY( _rxDataSourceDescriptor
->getPropertyValue( PROPERTY_CONNECTION_RESOURCE
) >>= sConnectionResource
);
886 if ( xPSI
->hasPropertyByName( PROPERTY_CONNECTION_INFO
) )
887 OSL_VERIFY( _rxDataSourceDescriptor
->getPropertyValue( PROPERTY_CONNECTION_INFO
) >>= aConnectionInfo
);
889 Reference
< XDriverManager
> xDriverManager
;
891 xDriverManager
.set( ConnectionPool::create( m_xContext
), UNO_QUERY_THROW
);
892 } catch( const Exception
& ) { }
893 if ( !xDriverManager
.is() )
894 // no connection pool installed
895 xDriverManager
.set( DriverManager::create( m_xContext
), UNO_QUERY_THROW
);
897 if ( aConnectionInfo
.getLength() )
898 xConnection
.set( xDriverManager
->getConnectionWithInfo( sConnectionResource
, aConnectionInfo
), UNO_SET_THROW
);
900 xConnection
.set( xDriverManager
->getConnection( sConnectionResource
), UNO_SET_THROW
);
904 if ( xInteractionHandler
!= m_xInteractionHandler
)
905 _out_rxDocInteractionHandler
= xInteractionHandler
;
910 ::utl::SharedUNOComponent
< XPreparedStatement
> CopyTableWizard::impl_createSourceStatement_throw() const
912 OSL_PRECOND( m_xSourceConnection
.is(), "CopyTableWizard::impl_createSourceStatement_throw: illegal call!" );
913 if ( !m_xSourceConnection
.is() )
914 throw RuntimeException( "CopyTableWizard::impl_createSourceStatement_throw: illegal call!", *const_cast< CopyTableWizard
* >( this ));
916 ::utl::SharedUNOComponent
< XPreparedStatement
> xStatement
;
917 switch ( m_nCommandType
)
919 case CommandType::TABLE
:
920 xStatement
.set( m_pSourceObject
->getPreparedSelectStatement(), UNO_SET_THROW
);
923 case CommandType::QUERY
:
925 OUString
sQueryCommand( m_pSourceObject
->getSelectStatement() );
926 xStatement
.set( m_pSourceObject
->getPreparedSelectStatement(), UNO_SET_THROW
);
928 // check whether we have to fill in parameter values
929 // create and fill a composer
931 Reference
< XMultiServiceFactory
> xFactory( m_xSourceConnection
, UNO_QUERY
);
932 ::utl::SharedUNOComponent
< XSingleSelectQueryComposer
> xComposer
;
934 // note: connections below the sdb-level are allowed to not support the XMultiServiceFactory interface
935 xComposer
.set( xFactory
->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER
), UNO_QUERY
);
937 if ( xComposer
.is() )
939 xComposer
->setQuery( sQueryCommand
);
941 Reference
< XParameters
> xStatementParams( xStatement
, UNO_QUERY
);
942 OSL_ENSURE( xStatementParams
.is(), "CopyTableWizard::impl_createSourceStatement_throw: no access to the statement's parameters!" );
943 // the statement should be a css.sdbc.PreparedStatement (this is what
944 // we created), and a prepared statement is required to support XParameters
945 if ( xStatementParams
.is() )
947 OSL_ENSURE( m_xInteractionHandler
.is(),
948 "CopyTableWizard::impl_createSourceStatement_throw: no interaction handler for the parameters request!" );
949 // we should always have an interaction handler - as last fallback, we create an own one in ::initialize
951 if ( m_xInteractionHandler
.is() )
952 ::dbtools::askForParameters( xComposer
, xStatementParams
, m_xSourceConnection
, m_xInteractionHandler
);
959 // this should not have survived initialization phase
960 throw RuntimeException("No case matched, this should not have survived the initialization phase", *const_cast< CopyTableWizard
* >( this ));
971 ValueTransfer( const sal_Int32
& _rSourcePos
, const sal_Int32
& _rDestPos
, const ::std::vector
< sal_Int32
>& _rColTypes
,
972 const Reference
< XRow
>& _rxSource
, const Reference
< XParameters
>& _rxDest
)
973 :m_rSourcePos( _rSourcePos
)
974 ,m_rDestPos( _rDestPos
)
975 ,m_rColTypes( _rColTypes
)
976 ,m_xSource( _rxSource
)
981 template< typename VALUE_TYPE
>
982 void transferValue( VALUE_TYPE ( SAL_CALL
XRow::*_pGetter
)( sal_Int32
),
983 void (SAL_CALL
XParameters::*_pSetter
)( sal_Int32
, VALUE_TYPE
) )
985 VALUE_TYPE
value( (m_xSource
.get()->*_pGetter
)( m_rSourcePos
) );
986 if ( m_xSource
->wasNull() )
987 m_xDest
->setNull( m_rDestPos
, m_rColTypes
[ m_rSourcePos
] );
989 (m_xDest
.get()->*_pSetter
)( m_rDestPos
, value
);
991 template< typename VALUE_TYPE
>
992 void transferComplexValue( VALUE_TYPE ( SAL_CALL
XRow::*_pGetter
)( sal_Int32
),
993 void (SAL_CALL
XParameters::*_pSetter
)( sal_Int32
, const VALUE_TYPE
& ) )
995 const VALUE_TYPE
value( (m_xSource
.get()->*_pGetter
)( m_rSourcePos
) );
997 if ( m_xSource
->wasNull() )
998 m_xDest
->setNull( m_rDestPos
, m_rColTypes
[ m_rSourcePos
] );
1000 (m_xDest
.get()->*_pSetter
)( m_rDestPos
, value
);
1004 const sal_Int32
& m_rSourcePos
;
1005 const sal_Int32
& m_rDestPos
;
1006 const ::std::vector
< sal_Int32
> m_rColTypes
;
1007 const Reference
< XRow
> m_xSource
;
1008 const Reference
< XParameters
> m_xDest
;
1012 bool CopyTableWizard::impl_processCopyError_nothrow( const CopyTableRowEvent
& _rEvent
)
1014 Reference
< XCopyTableListener
> xListener
;
1017 ::comphelper::OInterfaceIteratorHelper2
aIter( m_aCopyTableListeners
);
1018 while ( aIter
.hasMoreElements() )
1020 xListener
.set( aIter
.next(), UNO_QUERY_THROW
);
1021 sal_Int16 nListenerChoice
= xListener
->copyRowError( _rEvent
);
1022 switch ( nListenerChoice
)
1024 case CopyTableContinuation::Proceed
: return true; // continue copying
1025 case CopyTableContinuation::CallNextHandler
: continue; // continue the loop, ask next listener
1026 case CopyTableContinuation::Cancel
: return false; // cancel copying
1027 case CopyTableContinuation::AskUser
: break; // stop asking the listeners, ask the user
1030 SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_processCopyError_nothrow: invalid listener response!" );
1031 // ask next listener
1036 catch( const Exception
& )
1038 DBG_UNHANDLED_EXCEPTION();
1041 // no listener felt responsible for the error, or a listener told to ask the user
1046 aError
.Context
= *this;
1047 aError
.Message
= OUString( ModuleRes( STR_ERROR_OCCURRED_WHILE_COPYING
) );
1049 ::dbtools::SQLExceptionInfo
aInfo( _rEvent
.Error
);
1050 if ( aInfo
.isValid() )
1051 aError
.NextException
= _rEvent
.Error
;
1054 // a non-SQL exception happened
1055 Exception aException
;
1056 OSL_VERIFY( _rEvent
.Error
>>= aException
);
1057 SQLContext aContext
;
1058 aContext
.Context
= aException
.Context
;
1059 aContext
.Message
= aException
.Message
;
1060 aContext
.Details
= _rEvent
.Error
.getValueTypeName();
1061 aError
.NextException
<<= aContext
;
1064 ::rtl::Reference
< ::comphelper::OInteractionRequest
> xRequest( new ::comphelper::OInteractionRequest( makeAny( aError
) ) );
1066 ::rtl::Reference
< ::comphelper::OInteractionApprove
> xYes
= new ::comphelper::OInteractionApprove
;
1067 xRequest
->addContinuation( xYes
.get() );
1068 xRequest
->addContinuation( new ::comphelper::OInteractionDisapprove
);
1070 OSL_ENSURE( m_xInteractionHandler
.is(),
1071 "CopyTableWizard::impl_processCopyError_nothrow: we always should have an interaction handler!" );
1072 if ( m_xInteractionHandler
.is() )
1073 m_xInteractionHandler
->handle( xRequest
.get() );
1075 if ( xYes
->wasSelected() )
1079 catch( const Exception
& )
1081 DBG_UNHANDLED_EXCEPTION();
1088 void CopyTableWizard::impl_copyRows_throw( const Reference
< XResultSet
>& _rxSourceResultSet
,
1089 const Reference
< XPropertySet
>& _rxDestTable
)
1091 OSL_PRECOND( m_xDestConnection
.is(), "CopyTableWizard::impl_copyRows_throw: illegal call!" );
1092 if ( !m_xDestConnection
.is() )
1093 throw RuntimeException( "m_xDestConnection is set to null, CopyTableWizard::impl_copyRows_throw: illegal call!", *this );
1095 Reference
< XDatabaseMetaData
> xDestMetaData( m_xDestConnection
->getMetaData(), UNO_QUERY_THROW
);
1097 const OCopyTableWizard
& rWizard
= impl_getDialog_throw();
1098 ODatabaseExport::TPositions aColumnMapping
= rWizard
.GetColumnPositions();
1099 bool bAutoIncrement
= rWizard
.shouldCreatePrimaryKey();
1101 Reference
< XRow
> xRow ( _rxSourceResultSet
, UNO_QUERY_THROW
);
1102 Reference
< XRowLocate
> xRowLocate ( _rxSourceResultSet
, UNO_QUERY_THROW
);
1104 Reference
< XResultSetMetaDataSupplier
> xSuppResMeta( _rxSourceResultSet
, UNO_QUERY_THROW
);
1105 Reference
< XResultSetMetaData
> xMeta( xSuppResMeta
->getMetaData() );
1107 // we need a vector which all types
1108 sal_Int32 nCount
= xMeta
->getColumnCount();
1109 ::std::vector
< sal_Int32
> aSourceColTypes
;
1110 aSourceColTypes
.reserve( nCount
+ 1 );
1111 aSourceColTypes
.push_back( -1 ); // just to avoid a every time i-1 call
1113 ::std::vector
< sal_Int32
> aSourcePrec
;
1114 aSourcePrec
.reserve( nCount
+ 1 );
1115 aSourcePrec
.push_back( -1 ); // just to avoid a every time i-1 call
1117 for ( sal_Int32 k
=1; k
<= nCount
; ++k
)
1119 aSourceColTypes
.push_back( xMeta
->getColumnType( k
) );
1120 aSourcePrec
.push_back( xMeta
->getPrecision( k
) );
1123 // now create, fill and execute the prepared statement
1124 Reference
< XPreparedStatement
> xStatement( ODatabaseExport::createPreparedStatment( xDestMetaData
, _rxDestTable
, aColumnMapping
), UNO_SET_THROW
);
1125 Reference
< XParameters
> xStatementParams( xStatement
, UNO_QUERY_THROW
);
1127 const bool bSelectedRecordsOnly
= m_aSourceSelection
.getLength() != 0;
1128 const Any
* pSelectedRow
= m_aSourceSelection
.getConstArray();
1129 const Any
* pSelEnd
= pSelectedRow
+ m_aSourceSelection
.getLength();
1131 sal_Int32 nRowCount
= 0;
1132 bool bContinue
= false;
1134 CopyTableRowEvent aCopyEvent
;
1135 aCopyEvent
.Source
= *this;
1136 aCopyEvent
.SourceData
= _rxSourceResultSet
;
1138 do // loop as long as there are more rows or the selection ends
1141 if ( bSelectedRecordsOnly
)
1143 if ( pSelectedRow
!= pSelEnd
)
1145 if ( m_bSourceSelectionBookmarks
)
1147 bContinue
= xRowLocate
->moveToBookmark( *pSelectedRow
);
1152 OSL_VERIFY( *pSelectedRow
>>= nPos
);
1153 bContinue
= _rxSourceResultSet
->absolute( nPos
);
1159 bContinue
= _rxSourceResultSet
->next();
1167 ODatabaseExport::TPositions::const_iterator aPosIter
= aColumnMapping
.begin();
1168 ODatabaseExport::TPositions::const_iterator aPosEnd
= aColumnMapping
.end();
1170 aCopyEvent
.Error
.clear();
1173 bool bInsertAutoIncrement
= true;
1175 m_aCopyTableListeners
.notifyEach( &XCopyTableListener::copyingRow
, aCopyEvent
);
1177 sal_Int32
nDestColumn( 0 );
1178 sal_Int32
nSourceColumn( 1 );
1179 ValueTransfer
aTransfer( nSourceColumn
, nDestColumn
, aSourceColTypes
, xRow
, xStatementParams
);
1181 for ( ; aPosIter
!= aPosEnd
; ++aPosIter
)
1183 nDestColumn
= aPosIter
->first
;
1184 if ( nDestColumn
== COLUMN_POSITION_NOT_FOUND
)
1187 // otherwise we don't get the correct value when only the 2nd source column was selected
1191 if ( bAutoIncrement
&& bInsertAutoIncrement
)
1193 xStatementParams
->setInt( 1, nRowCount
);
1194 bInsertAutoIncrement
= false;
1198 if ( ( nSourceColumn
< 1 ) || ( nSourceColumn
>= (sal_Int32
)aSourceColTypes
.size() ) )
1199 { // ( we have to check here against 1 because the parameters are 1 based)
1200 ::dbtools::throwSQLException("Internal error: invalid column type index.",
1201 ::dbtools::StandardSQLState::INVALID_DESCRIPTOR_INDEX
, *this);
1204 switch ( aSourceColTypes
[ nSourceColumn
] )
1206 case DataType::DOUBLE
:
1207 case DataType::REAL
:
1208 aTransfer
.transferValue( &XRow::getDouble
, &XParameters::setDouble
);
1211 case DataType::CHAR
:
1212 case DataType::VARCHAR
:
1213 case DataType::LONGVARCHAR
:
1214 case DataType::DECIMAL
:
1215 case DataType::NUMERIC
:
1216 aTransfer
.transferComplexValue( &XRow::getString
, &XParameters::setString
);
1219 case DataType::BIGINT
:
1220 aTransfer
.transferValue( &XRow::getLong
, &XParameters::setLong
);
1223 case DataType::FLOAT
:
1224 aTransfer
.transferValue( &XRow::getFloat
, &XParameters::setFloat
);
1227 case DataType::LONGVARBINARY
:
1228 case DataType::BINARY
:
1229 case DataType::VARBINARY
:
1230 aTransfer
.transferComplexValue( &XRow::getBytes
, &XParameters::setBytes
);
1233 case DataType::DATE
:
1234 aTransfer
.transferComplexValue( &XRow::getDate
, &XParameters::setDate
);
1237 case DataType::TIME
:
1238 aTransfer
.transferComplexValue( &XRow::getTime
, &XParameters::setTime
);
1241 case DataType::TIMESTAMP
:
1242 aTransfer
.transferComplexValue( &XRow::getTimestamp
, &XParameters::setTimestamp
);
1246 if ( aSourcePrec
[nSourceColumn
] > 1 )
1248 aTransfer
.transferComplexValue( &XRow::getBytes
, &XParameters::setBytes
);
1252 case DataType::BOOLEAN
:
1253 aTransfer
.transferValue( &XRow::getBoolean
, &XParameters::setBoolean
);
1256 case DataType::TINYINT
:
1257 aTransfer
.transferValue( &XRow::getByte
, &XParameters::setByte
);
1260 case DataType::SMALLINT
:
1261 aTransfer
.transferValue( &XRow::getShort
, &XParameters::setShort
);
1264 case DataType::INTEGER
:
1265 aTransfer
.transferValue( &XRow::getInt
, &XParameters::setInt
);
1268 case DataType::BLOB
:
1269 aTransfer
.transferComplexValue( &XRow::getBlob
, &XParameters::setBlob
);
1272 case DataType::CLOB
:
1273 aTransfer
.transferComplexValue( &XRow::getClob
, &XParameters::setClob
);
1278 OUString
aMessage( ModuleRes( STR_CTW_UNSUPPORTED_COLUMN_TYPE
) );
1280 aMessage
= aMessage
.replaceFirst( "$type$", OUString::number( aSourceColTypes
[ nSourceColumn
] ) );
1281 aMessage
= aMessage
.replaceFirst( "$pos$", OUString::number( nSourceColumn
) );
1283 ::dbtools::throwSQLException(
1285 ::dbtools::StandardSQLState::INVALID_SQL_DATA_TYPE
,
1292 xStatement
->executeUpdate();
1295 m_aCopyTableListeners
.notifyEach( &XCopyTableListener::copiedRow
, aCopyEvent
);
1297 catch( const Exception
& )
1299 aCopyEvent
.Error
= ::cppu::getCaughtException();
1302 if ( aCopyEvent
.Error
.hasValue() )
1303 bContinue
= impl_processCopyError_nothrow( aCopyEvent
);
1308 void CopyTableWizard::impl_doCopy_nothrow()
1314 OCopyTableWizard
& rWizard( impl_getDialog_throw() );
1316 WaitObject
aWO( rWizard
.GetParent() );
1317 Reference
< XPropertySet
> xTable
;
1319 switch ( rWizard
.getOperation() )
1321 case CopyTableOperation::CopyDefinitionOnly
:
1322 case CopyTableOperation::CopyDefinitionAndData
:
1324 xTable
= rWizard
.createTable();
1328 SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_doCopy_nothrow: createTable should throw here, shouldn't it?" );
1332 if( CopyTableOperation::CopyDefinitionOnly
== rWizard
.getOperation() )
1338 case CopyTableOperation::AppendData
:
1343 xTable
= rWizard
.createTable();
1346 SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_doCopy_nothrow: createTable should throw here, shouldn't it?" );
1351 ::utl::SharedUNOComponent
< XPreparedStatement
> xSourceStatement
;
1352 ::utl::SharedUNOComponent
< XResultSet
> xSourceResultSet
;
1354 if ( m_xSourceResultSet
.is() )
1356 xSourceResultSet
.reset( m_xSourceResultSet
, ::utl::SharedUNOComponent
< XResultSet
>::NoTakeOwnership
);
1360 const bool bIsSameConnection
= ( m_xSourceConnection
.getTyped() == m_xDestConnection
.getTyped() );
1361 const bool bIsTable
= ( CommandType::TABLE
== m_nCommandType
);
1363 if ( bIsSameConnection
&& bIsTable
)
1365 // try whether the server supports copying via SQL
1368 m_xDestConnection
->createStatement()->executeUpdate( impl_getServerSideCopyStatement_throw(xTable
) );
1371 catch( const Exception
& )
1379 xSourceStatement
.set( impl_createSourceStatement_throw(), UNO_SET_THROW
);
1380 xSourceResultSet
.set( xSourceStatement
->executeQuery(), UNO_SET_THROW
);
1384 if ( xSourceResultSet
.is() )
1385 impl_copyRows_throw( xSourceResultSet
, xTable
);
1389 case CopyTableOperation::CreateAsView
:
1390 rWizard
.createView();
1394 SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_doCopy_nothrow: What operation, please?" );
1398 catch( const Exception
& )
1400 aError
= ::cppu::getCaughtException();
1402 // silence the error of the user cancelling the parameter's dialog
1403 SQLException aSQLError
;
1404 if ( ( aError
>>= aSQLError
) && ( aSQLError
.ErrorCode
== ::dbtools::ParameterInteractionCancelled
) )
1407 m_nOverrideExecutionResult
= RET_CANCEL
;
1411 if ( aError
.hasValue() && m_xInteractionHandler
.is() )
1415 ::rtl::Reference
< ::comphelper::OInteractionRequest
> xRequest( new ::comphelper::OInteractionRequest( aError
) );
1416 m_xInteractionHandler
->handle( xRequest
.get() );
1418 catch( const Exception
& )
1420 DBG_UNHANDLED_EXCEPTION();
1425 OUString
CopyTableWizard::impl_getServerSideCopyStatement_throw(const Reference
< XPropertySet
>& _xTable
)
1427 const Reference
<XColumnsSupplier
> xDestColsSup(_xTable
,UNO_QUERY_THROW
);
1428 const Sequence
< OUString
> aDestColumnNames
= xDestColsSup
->getColumns()->getElementNames();
1429 const Reference
< XDatabaseMetaData
> xDestMetaData( m_xDestConnection
->getMetaData(), UNO_QUERY_THROW
);
1430 const OUString sQuote
= xDestMetaData
->getIdentifierQuoteString();
1431 OUStringBuffer sColumns
;
1432 // 1st check if the columns matching
1433 const OCopyTableWizard
& rWizard
= impl_getDialog_throw();
1434 ODatabaseExport::TPositions aColumnMapping
= rWizard
.GetColumnPositions();
1435 ODatabaseExport::TPositions::const_iterator aPosIter
= aColumnMapping
.begin();
1436 for ( sal_Int32 i
= 0; aPosIter
!= aColumnMapping
.end() ; ++aPosIter
,++i
)
1438 if ( COLUMN_POSITION_NOT_FOUND
!= aPosIter
->second
)
1440 if ( !sColumns
.isEmpty() )
1441 sColumns
.append(",");
1442 sColumns
.append(sQuote
+ aDestColumnNames
[aPosIter
->second
- 1] + sQuote
);
1445 const OUString sComposedTableName
= ::dbtools::composeTableName( xDestMetaData
, _xTable
, ::dbtools::EComposeRule::InDataManipulation
, false, false, true );
1446 OUString
sSql("INSERT INTO " + sComposedTableName
+ " ( " + sColumns
.makeStringAndClear() + " ) ( " + m_pSourceObject
->getSelectStatement() + " )");
1451 void SAL_CALL
CopyTableWizard::initialize( const Sequence
< Any
>& _rArguments
) throw (Exception
, RuntimeException
, std::exception
)
1453 ::osl::MutexGuard
aGuard( m_aMutex
);
1454 if ( isInitialized() )
1455 throw AlreadyInitializedException( OUString(), *this );
1457 sal_Int32
nArgCount( _rArguments
.getLength() );
1458 if ( ( nArgCount
!= 2 ) && ( nArgCount
!= 3 ) )
1459 throw IllegalArgumentException(
1460 OUString( ModuleRes( STR_CTW_ILLEGAL_PARAMETER_COUNT
) ),
1467 if ( nArgCount
== 3 )
1468 { // ->createWithInteractionHandler
1469 if ( !( _rArguments
[2] >>= m_xInteractionHandler
) )
1470 throw IllegalArgumentException(
1471 OUString(ModuleRes( STR_CTW_ERROR_INVALID_INTERACTIONHANDLER
)),
1476 if ( !m_xInteractionHandler
.is() )
1477 m_xInteractionHandler
.set( InteractionHandler::createWithParent(m_xContext
, nullptr), UNO_QUERY
);
1479 Reference
< XInteractionHandler
> xSourceDocHandler
;
1480 Reference
< XPropertySet
> xSourceDescriptor( impl_ensureDataAccessDescriptor_throw( _rArguments
, 0, m_xSourceConnection
, xSourceDocHandler
) );
1481 impl_checkForUnsupportedSettings_throw( xSourceDescriptor
);
1482 m_pSourceObject
= impl_extractSourceObject_throw( xSourceDescriptor
, m_nCommandType
);
1483 impl_extractSourceResultSet_throw( xSourceDescriptor
);
1485 Reference
< XInteractionHandler
> xDestDocHandler
;
1486 impl_ensureDataAccessDescriptor_throw( _rArguments
, 1, m_xDestConnection
, xDestDocHandler
);
1488 if ( xDestDocHandler
.is() && !m_xInteractionHandler
.is() )
1489 m_xInteractionHandler
= xDestDocHandler
;
1491 catch( const RuntimeException
& ) { throw; }
1492 catch( const SQLException
& ) { throw; }
1493 catch( const Exception
& )
1495 throw WrappedTargetException(
1496 OUString( ModuleRes( STR_CTW_ERROR_DURING_INITIALIZATION
) ),
1498 ::cppu::getCaughtException()
1503 ::cppu::IPropertyArrayHelper
& CopyTableWizard::getInfoHelper()
1505 return *getArrayHelper();
1508 ::cppu::IPropertyArrayHelper
* CopyTableWizard::createArrayHelper( ) const
1510 Sequence
< Property
> aProps
;
1511 describeProperties( aProps
);
1512 return new ::cppu::OPropertyArrayHelper( aProps
);
1515 VclPtr
<Dialog
> CopyTableWizard::createDialog( vcl::Window
* _pParent
)
1517 OSL_PRECOND( isInitialized(), "CopyTableWizard::createDialog: not initialized!" );
1518 // this should have been prevented in ::execute already
1520 VclPtrInstance
<OCopyTableWizard
> pWizard(
1522 m_sDestinationTable
,
1525 m_xSourceConnection
.getTyped(),
1526 m_xDestConnection
.getTyped(),
1528 m_xInteractionHandler
1531 impl_attributesToDialog_nothrow( *pWizard
);
1536 void CopyTableWizard::executedDialog( sal_Int16 _nExecutionResult
)
1538 CopyTableWizard_DialogBase::executedDialog( _nExecutionResult
);
1540 if ( _nExecutionResult
== RET_OK
)
1541 impl_doCopy_nothrow();
1543 // do this after impl_doCopy_nothrow: The attributes may change during copying, for instance
1544 // if the user entered an unqualified table name
1545 impl_dialogToAttributes_nothrow( impl_getDialog_throw() );
1548 } // namespace dbaui
1550 extern "C" void SAL_CALL
createRegistryInfo_CopyTableWizard()
1552 static ::dbaui::OMultiInstanceAutoRegistration
< ::dbaui::CopyTableWizard
> aAutoRegistration
;
1555 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */