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 .
21 #include <strings.hrc>
22 #include <strings.hxx>
23 #include <core_resource.hxx>
24 #include <WCopyTable.hxx>
26 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
27 #include <com/sun/star/sdb/application/XCopyTableWizard.hpp>
28 #include <com/sun/star/sdb/application/CopyTableContinuation.hpp>
29 #include <com/sun/star/sdb/application/CopyTableOperation.hpp>
30 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
31 #include <com/sun/star/lang/NotInitializedException.hpp>
32 #include <com/sun/star/sdbc/XDataSource.hpp>
33 #include <com/sun/star/sdbc/DataType.hpp>
34 #include <com/sun/star/container/XNameAccess.hpp>
35 #include <com/sun/star/container/XChild.hpp>
36 #include <com/sun/star/task/InteractionHandler.hpp>
37 #include <com/sun/star/frame/XModel.hpp>
38 #include <com/sun/star/sdb/DatabaseContext.hpp>
39 #include <com/sun/star/sdb/XDocumentDataSource.hpp>
40 #include <com/sun/star/sdb/XCompletedConnection.hpp>
41 #include <com/sun/star/sdb/CommandType.hpp>
42 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
43 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
44 #include <com/sun/star/lang/DisposedException.hpp>
45 #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
46 #include <com/sun/star/sdbc/XParameters.hpp>
47 #include <com/sun/star/sdbc/XRow.hpp>
48 #include <com/sun/star/sdbcx/XRowLocate.hpp>
49 #include <com/sun/star/sdbc/XResultSetMetaDataSupplier.hpp>
50 #include <com/sun/star/sdb/SQLContext.hpp>
51 #include <com/sun/star/sdbc/DriverManager.hpp>
52 #include <com/sun/star/sdbc/ConnectionPool.hpp>
54 #include <comphelper/processfactory.hxx>
55 #include <comphelper/interaction.hxx>
56 #include <comphelper/namedvaluecollection.hxx>
57 #include <comphelper/proparrhlp.hxx>
58 #include <connectivity/dbexception.hxx>
59 #include <connectivity/dbtools.hxx>
60 #include <cppuhelper/exc_hlp.hxx>
61 #include <cppuhelper/implbase.hxx>
62 #include <comphelper/interfacecontainer3.hxx>
63 #include <o3tl/safeint.hxx>
64 #include <rtl/ustrbuf.hxx>
65 #include <sal/log.hxx>
66 #include <svtools/genericunodialog.hxx>
67 #include <toolkit/helper/vclunohelper.hxx>
68 #include <comphelper/diagnose_ex.hxx>
69 #include <unotools/sharedunocomponent.hxx>
70 #include <vcl/svapp.hxx>
75 using ::com::sun::star::uno::Reference
;
76 using ::com::sun::star::uno::XInterface
;
77 using ::com::sun::star::uno::UNO_QUERY
;
78 using ::com::sun::star::uno::UNO_QUERY_THROW
;
79 using ::com::sun::star::uno::UNO_SET_THROW
;
80 using ::com::sun::star::uno::Exception
;
81 using ::com::sun::star::uno::RuntimeException
;
82 using ::com::sun::star::uno::Any
;
83 using ::com::sun::star::uno::Sequence
;
84 using ::com::sun::star::uno::XComponentContext
;
85 using ::com::sun::star::beans::XPropertySetInfo
;
86 using ::com::sun::star::lang::XMultiServiceFactory
;
87 using ::com::sun::star::beans::Property
;
88 using ::com::sun::star::sdb::application::XCopyTableWizard
;
89 using ::com::sun::star::sdb::application::XCopyTableListener
;
90 using ::com::sun::star::sdb::application::CopyTableRowEvent
;
91 using ::com::sun::star::beans::Optional
;
92 using ::com::sun::star::lang::IllegalArgumentException
;
93 using ::com::sun::star::ucb::AlreadyInitializedException
;
94 using ::com::sun::star::beans::XPropertySet
;
95 using ::com::sun::star::lang::NotInitializedException
;
96 using ::com::sun::star::lang::XServiceInfo
;
97 using ::com::sun::star::sdbc::XConnection
;
98 using ::com::sun::star::sdbc::XDataSource
;
99 using ::com::sun::star::container::XNameAccess
;
100 using ::com::sun::star::container::XChild
;
101 using ::com::sun::star::task::InteractionHandler
;
102 using ::com::sun::star::task::XInteractionHandler
;
103 using ::com::sun::star::frame::XModel
;
104 using ::com::sun::star::sdb::DatabaseContext
;
105 using ::com::sun::star::sdb::XDatabaseContext
;
106 using ::com::sun::star::sdb::XDocumentDataSource
;
107 using ::com::sun::star::sdb::XCompletedConnection
;
108 using ::com::sun::star::lang::WrappedTargetException
;
109 using ::com::sun::star::sdbcx::XTablesSupplier
;
110 using ::com::sun::star::sdb::XQueriesSupplier
;
111 using ::com::sun::star::lang::DisposedException
;
112 using ::com::sun::star::sdbc::XPreparedStatement
;
113 using ::com::sun::star::sdb::XSingleSelectQueryComposer
;
114 using ::com::sun::star::sdbc::XDatabaseMetaData
;
115 using ::com::sun::star::sdbcx::XColumnsSupplier
;
116 using ::com::sun::star::sdbc::XParameters
;
117 using ::com::sun::star::sdbc::XResultSet
;
118 using ::com::sun::star::sdbc::XRow
;
119 using ::com::sun::star::sdbcx::XRowLocate
;
120 using ::com::sun::star::sdbc::XResultSetMetaDataSupplier
;
121 using ::com::sun::star::sdbc::XResultSetMetaData
;
122 using ::com::sun::star::sdbc::SQLException
;
123 using ::com::sun::star::sdb::SQLContext
;
124 using ::com::sun::star::sdbc::ConnectionPool
;
125 using ::com::sun::star::sdbc::XDriverManager
;
126 using ::com::sun::star::sdbc::DriverManager
;
127 using ::com::sun::star::beans::PropertyValue
;
129 namespace CopyTableOperation
= ::com::sun::star::sdb::application::CopyTableOperation
;
130 namespace CopyTableContinuation
= ::com::sun::star::sdb::application::CopyTableContinuation
;
131 namespace CommandType
= ::com::sun::star::sdb::CommandType
;
132 namespace DataType
= ::com::sun::star::sdbc::DataType
;
134 typedef ::utl::SharedUNOComponent
< XConnection
> SharedConnection
;
137 typedef ::svt::OGenericUnoDialog CopyTableWizard_DialogBase
;
138 typedef ::cppu::ImplInheritanceHelper
< CopyTableWizard_DialogBase
140 > CopyTableWizard_Base
;
144 class CopyTableWizard
145 :public CopyTableWizard_Base
146 ,public ::comphelper::OPropertyArrayUsageHelper
< CopyTableWizard
>
150 virtual OUString SAL_CALL
getImplementationName() override
;
151 virtual css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
;
154 virtual ::sal_Int16 SAL_CALL
getOperation() override
;
155 virtual void SAL_CALL
setOperation( ::sal_Int16 _operation
) override
;
156 virtual OUString SAL_CALL
getDestinationTableName() override
;
157 virtual void SAL_CALL
setDestinationTableName( const OUString
& _destinationTableName
) override
;
158 virtual Optional
< OUString
> SAL_CALL
getCreatePrimaryKey() override
;
159 virtual void SAL_CALL
setCreatePrimaryKey( const Optional
< OUString
>& _newPrimaryKey
) override
;
160 virtual sal_Bool SAL_CALL
getUseHeaderLineAsColumnNames() override
;
161 virtual void SAL_CALL
setUseHeaderLineAsColumnNames( sal_Bool _bUseHeaderLineAsColumnNames
) override
;
162 virtual void SAL_CALL
addCopyTableListener( const Reference
< XCopyTableListener
>& Listener
) override
;
163 virtual void SAL_CALL
removeCopyTableListener( const Reference
< XCopyTableListener
>& Listener
) override
;
165 // XCopyTableWizard::XExecutableDialog
166 virtual void SAL_CALL
setTitle( const OUString
& aTitle
) override
;
167 virtual ::sal_Int16 SAL_CALL
execute( ) override
;
170 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) override
;
173 virtual Reference
< XPropertySetInfo
> SAL_CALL
getPropertySetInfo() override
;
174 virtual ::cppu::IPropertyArrayHelper
& SAL_CALL
getInfoHelper() override
;
176 // OPropertyArrayUsageHelper
177 virtual ::cppu::IPropertyArrayHelper
* createArrayHelper( ) const override
;
180 ::osl::Mutex
& getMutex() { return m_aMutex
; }
181 bool isInitialized() const { return m_xSourceConnection
.is() && m_pSourceObject
&& m_xDestConnection
.is(); }
183 explicit CopyTableWizard( const Reference
< XComponentContext
>& _rxORB
);
184 virtual ~CopyTableWizard() override
;
187 // OGenericUnoDialog overridables
188 virtual std::unique_ptr
<weld::DialogController
> createDialog(const css::uno::Reference
<css::awt::XWindow
>& rParent
) override
;
189 virtual void executedDialog( sal_Int16 _nExecutionResult
) override
;
192 /// ensures our current attribute values are reflected in the dialog
193 void impl_attributesToDialog_nothrow( OCopyTableWizard
& _rDialog
) const;
195 /// ensures the current dialog settings are reflected in our attributes
196 void impl_dialogToAttributes_nothrow( const OCopyTableWizard
& _rDialog
);
198 /** returns our typed dialog
200 @throws css::uno::RuntimeException
201 if we don't have a dialog at the moment the method is called
204 impl_getDialog_throw();
206 /** ensures the given argument sequence contains a valid data access descriptor at the given position
208 the arguments as passed to ->initialize
210 the position within ->_rAllArgs which contains the data access descriptor
211 @param _out_rxConnection
212 will, upon successful return, contain the connection for the data source
213 @param _out_rxDocInteractionHandler
214 will, upon successful return, contain the interaction handler which could
215 be deduced from database document described by the descriptor, if any.
216 (It is possible that the descriptor does not allow to deduce a database document,
217 in which case <code>_out_rxDocInteractionHandler</code> will be <NULL/>.)
218 @return the data access descriptor
220 Reference
< XPropertySet
>
221 impl_ensureDataAccessDescriptor_throw(
222 const Sequence
< Any
>& _rAllArgs
,
223 const sal_Int16 _nArgPos
,
224 SharedConnection
& _out_rxConnection
,
225 Reference
< XInteractionHandler
>& _out_rxDocInteractionHandler
228 /** extracts the source object (table or query) described by the given descriptor,
229 relative to m_xSourceConnection
231 std::unique_ptr
< ICopyTableSourceObject
>
232 impl_extractSourceObject_throw(
233 const Reference
< XPropertySet
>& _rxDescriptor
,
234 sal_Int32
& _out_rCommandType
237 /** extracts the result set to copy records from, and the selection-related aspects, if any.
239 Effectively, this method extracts m_xSourceResultSet, m_aSourceSelection, and m_bSourceSelectionBookmarks.
241 If an inconsistent/insufficient sub set of those properties is present in the descriptor, and exception
244 void impl_extractSourceResultSet_throw(
245 const Reference
< XPropertySet
>& i_rDescriptor
248 /** checks whether the given copy source descriptor contains settings which are not
251 Throws an IllegalArgumentException if the descriptor contains a valid setting, which is
254 void impl_checkForUnsupportedSettings_throw(
255 const Reference
< XPropertySet
>& _rxSourceDescriptor
) const;
257 /** obtains the connection described by the given data access descriptor
259 If needed and possible, the method will ask the user, using the interaction
260 handler associated with the database described by the descriptor.
262 All errors are handled with the InteractionHandler associated with the data source,
263 if there is one. Else, they will be silenced (but asserted in non-product builds).
265 @param _rxDataSourceDescriptor
266 the data access descriptor describing the data source whose connection
267 should be obtained. Must not be <NULL/>.
268 @param _out_rxDocInteractionHandler
269 the interaction handler which could be deduced from the descriptor
271 @throws RuntimeException
272 if anything goes seriously wrong.
275 impl_extractConnection_throw(
276 const Reference
< XPropertySet
>& _rxDataSourceDescriptor
,
277 Reference
< XInteractionHandler
>& _out_rxDocInteractionHandler
280 /** actually copies the table
282 This method is called after the dialog has been successfully executed.
284 void impl_doCopy_nothrow();
286 /** creates the INSERT INTO statement
287 @param _xTable The destination table.
289 OUString
impl_getServerSideCopyStatement_throw( const Reference
< XPropertySet
>& _xTable
);
291 /** creates the statement which, when executed, will produce the source data to copy
293 If the source object refers to a query which contains parameters, those parameters
294 are filled in, using an interaction handler.
296 ::utl::SharedUNOComponent
< XPreparedStatement
>
297 impl_createSourceStatement_throw() const;
299 /** copies the data rows from the given source result set to the given destination table
301 void impl_copyRows_throw(
302 const Reference
< XResultSet
>& _rxSourceResultSet
,
303 const Reference
< XPropertySet
>& _rxDestTable
306 /** processes an error which occurred during copying
308 First, all listeners are ask. If a listener tells to cancel or continue copying, this is reported to the
309 method's caller. If a listener tells to ask the user, this is done, and the user's decision is
310 reported to the method's caller.
313 <TRUE/> if and only if copying should be continued.
315 bool impl_processCopyError_nothrow(
316 const CopyTableRowEvent
& _rEvent
);
319 Reference
<XComponentContext
> m_xContext
;
322 sal_Int16 m_nOperation
;
323 OUString m_sDestinationTable
;
324 Optional
< OUString
> m_aPrimaryKeyName
;
325 bool m_bUseHeaderLineAsColumnNames
;
328 SharedConnection m_xSourceConnection
;
329 sal_Int32 m_nCommandType
;
330 std::unique_ptr
< ICopyTableSourceObject
>
332 Reference
< XResultSet
> m_xSourceResultSet
;
333 Sequence
< Any
> m_aSourceSelection
;
334 bool m_bSourceSelectionBookmarks
;
337 SharedConnection m_xDestConnection
;
340 Reference
< XInteractionHandler
> m_xInteractionHandler
;
341 ::comphelper::OInterfaceContainerHelper3
<XCopyTableListener
>
342 m_aCopyTableListeners
;
343 sal_Int16 m_nOverrideExecutionResult
;
347 class CopyTableAccessGuard
350 explicit CopyTableAccessGuard( CopyTableWizard
& _rWizard
)
351 :m_rWizard( _rWizard
)
353 m_rWizard
.getMutex().acquire();
354 if ( !m_rWizard
.isInitialized() )
355 throw NotInitializedException();
358 ~CopyTableAccessGuard()
360 m_rWizard
.getMutex().release();
364 CopyTableWizard
& m_rWizard
;
369 CopyTableWizard::CopyTableWizard( const Reference
< XComponentContext
>& _rxORB
)
370 :CopyTableWizard_Base( _rxORB
)
371 ,m_xContext( _rxORB
)
372 ,m_nOperation( CopyTableOperation::CopyDefinitionAndData
)
373 ,m_aPrimaryKeyName( false, "ID" )
374 ,m_bUseHeaderLineAsColumnNames( true )
375 ,m_nCommandType( CommandType::COMMAND
)
376 ,m_bSourceSelectionBookmarks( true )
377 ,m_aCopyTableListeners( m_aMutex
)
378 ,m_nOverrideExecutionResult( -1 )
382 CopyTableWizard::~CopyTableWizard()
386 // protect some members whose dtor might potentially throw
387 try { m_xSourceConnection
.clear(); }
388 catch( const Exception
& ) { DBG_UNHANDLED_EXCEPTION("dbaccess"); }
389 try { m_xDestConnection
.clear(); }
390 catch( const Exception
& ) { DBG_UNHANDLED_EXCEPTION("dbaccess"); }
392 // TODO: shouldn't we have explicit disposal support? If a listener is registered
393 // at our instance, and perhaps holds this our instance by a hard ref, then we'll never
395 // However, adding XComponent support to the GenericUNODialog probably requires
396 // some thinking - would it break existing clients which do not call a dispose, then?
399 OUString SAL_CALL
CopyTableWizard::getImplementationName()
401 return "org.openoffice.comp.dbu.CopyTableWizard";
404 css::uno::Sequence
<OUString
> SAL_CALL
CopyTableWizard::getSupportedServiceNames()
406 return { "com.sun.star.sdb.application.CopyTableWizard" };
409 Reference
< XPropertySetInfo
> SAL_CALL
CopyTableWizard::getPropertySetInfo()
411 Reference
< XPropertySetInfo
> xInfo( createPropertySetInfo( getInfoHelper() ) );
415 ::sal_Int16 SAL_CALL
CopyTableWizard::getOperation()
417 CopyTableAccessGuard
aGuard( *this );
421 void SAL_CALL
CopyTableWizard::setOperation( ::sal_Int16 _operation
)
423 CopyTableAccessGuard
aGuard( *this );
425 if ( ( _operation
!= CopyTableOperation::CopyDefinitionAndData
)
426 && ( _operation
!= CopyTableOperation::CopyDefinitionOnly
)
427 && ( _operation
!= CopyTableOperation::CreateAsView
)
428 && ( _operation
!= CopyTableOperation::AppendData
)
430 throw IllegalArgumentException( OUString(), *this, 1 );
432 if ( ( _operation
== CopyTableOperation::CreateAsView
)
433 && !OCopyTableWizard::supportsViews( m_xDestConnection
)
435 throw IllegalArgumentException(
436 DBA_RES( STR_CTW_NO_VIEWS_SUPPORT
),
441 m_nOperation
= _operation
;
444 OUString SAL_CALL
CopyTableWizard::getDestinationTableName()
446 CopyTableAccessGuard
aGuard( *this );
447 return m_sDestinationTable
;
450 void SAL_CALL
CopyTableWizard::setDestinationTableName( const OUString
& _destinationTableName
)
452 CopyTableAccessGuard
aGuard( *this );
453 m_sDestinationTable
= _destinationTableName
;
456 Optional
< OUString
> SAL_CALL
CopyTableWizard::getCreatePrimaryKey()
458 CopyTableAccessGuard
aGuard( *this );
459 return m_aPrimaryKeyName
;
462 void SAL_CALL
CopyTableWizard::setCreatePrimaryKey( const Optional
< OUString
>& _newPrimaryKey
)
464 CopyTableAccessGuard
aGuard( *this );
466 if ( _newPrimaryKey
.IsPresent
&& !OCopyTableWizard::supportsPrimaryKey( m_xDestConnection
) )
467 throw IllegalArgumentException(
468 DBA_RES( STR_CTW_NO_PRIMARY_KEY_SUPPORT
),
473 m_aPrimaryKeyName
= _newPrimaryKey
;
476 sal_Bool SAL_CALL
CopyTableWizard::getUseHeaderLineAsColumnNames()
478 CopyTableAccessGuard
aGuard( *this );
479 return m_bUseHeaderLineAsColumnNames
;
482 void SAL_CALL
CopyTableWizard::setUseHeaderLineAsColumnNames( sal_Bool _bUseHeaderLineAsColumnNames
)
484 CopyTableAccessGuard
aGuard( *this );
485 m_bUseHeaderLineAsColumnNames
= _bUseHeaderLineAsColumnNames
;
488 void SAL_CALL
CopyTableWizard::addCopyTableListener( const Reference
< XCopyTableListener
>& _rxListener
)
490 CopyTableAccessGuard
aGuard( *this );
491 if ( _rxListener
.is() )
492 m_aCopyTableListeners
.addInterface( _rxListener
);
495 void SAL_CALL
CopyTableWizard::removeCopyTableListener( const Reference
< XCopyTableListener
>& _rxListener
)
497 CopyTableAccessGuard
aGuard( *this );
498 if ( _rxListener
.is() )
499 m_aCopyTableListeners
.removeInterface( _rxListener
);
502 void SAL_CALL
CopyTableWizard::setTitle( const OUString
& _rTitle
)
504 CopyTableAccessGuard
aGuard( *this );
505 CopyTableWizard_DialogBase::setTitle( _rTitle
);
508 ::sal_Int16 SAL_CALL
CopyTableWizard::execute( )
510 CopyTableAccessGuard
aGuard( *this );
512 m_nOverrideExecutionResult
= -1;
513 sal_Int16 nExecutionResult
= CopyTableWizard_DialogBase::execute();
514 if ( m_nOverrideExecutionResult
)
515 nExecutionResult
= m_nOverrideExecutionResult
;
517 return nExecutionResult
;
520 OCopyTableWizard
& CopyTableWizard::impl_getDialog_throw()
522 OCopyTableWizard
* pWizard
= dynamic_cast<OCopyTableWizard
*>(m_xDialog
.get());
524 throw DisposedException( OUString(), *this );
528 void CopyTableWizard::impl_attributesToDialog_nothrow( OCopyTableWizard
& _rDialog
) const
530 // primary key column
531 _rDialog
.setCreatePrimaryKey( m_aPrimaryKeyName
.IsPresent
, m_aPrimaryKeyName
.Value
);
532 _rDialog
.setUseHeaderLine(m_bUseHeaderLineAsColumnNames
);
534 // everything else was passed at construction time already
537 void CopyTableWizard::impl_dialogToAttributes_nothrow( const OCopyTableWizard
& _rDialog
)
539 m_aPrimaryKeyName
.IsPresent
= _rDialog
.shouldCreatePrimaryKey();
540 if ( m_aPrimaryKeyName
.IsPresent
)
541 m_aPrimaryKeyName
.Value
= _rDialog
.getPrimaryKeyName();
543 m_aPrimaryKeyName
.Value
.clear();
545 m_sDestinationTable
= _rDialog
.getName();
547 m_nOperation
= _rDialog
.getOperation();
548 m_bUseHeaderLineAsColumnNames
= _rDialog
.UseHeaderLine();
553 /** tries to obtain the InteractionHandler associated with a given data source
555 If the data source is a sdb-level data source, it will have a DatabaseDocument associated
556 with it. This document may have an InteractionHandler used while loading it.
558 @throws RuntimeException
559 if it occurs during invoking any of the data source's methods, or if any of the involved
560 components violates its contract by not providing the required interfaces
562 Reference
< XInteractionHandler
> lcl_getInteractionHandler_throw( const Reference
< XDataSource
>& _rxDataSource
, const Reference
< XInteractionHandler
>& _rFallback
)
564 Reference
< XInteractionHandler
> xHandler( _rFallback
);
566 // try to obtain the document model
567 Reference
< XModel
> xDocumentModel
;
568 Reference
< XDocumentDataSource
> xDocDataSource( _rxDataSource
, UNO_QUERY
);
569 if ( xDocDataSource
.is() )
570 xDocumentModel
.set( xDocDataSource
->getDatabaseDocument(), UNO_QUERY_THROW
);
572 // see whether the document model can provide a handler
573 if ( xDocumentModel
.is() )
575 xHandler
= ::comphelper::NamedValueCollection::getOrDefault( xDocumentModel
->getArgs(), u
"InteractionHandler", xHandler
);
580 /** tries to obtain the InteractionHandler associated with a given connection
582 If the connection belongs to a sdb-level data source, then this data source
583 is examined for an interaction handler. Else, <NULL/> is returned.
585 @throws RuntimeException
586 if it occurs during invoking any of the data source's methods, or if any of the involved
587 components violates its contract by not providing the required interfaces
589 Reference
< XInteractionHandler
> lcl_getInteractionHandler_throw( const Reference
< XConnection
>& _rxConnection
, const Reference
< XInteractionHandler
>& _rFallback
)
591 // try whether there is a data source which the connection belongs to
592 Reference
< XDataSource
> xDataSource
;
593 Reference
< XChild
> xAsChild( _rxConnection
, UNO_QUERY
);
595 xDataSource
.set(xAsChild
->getParent(), css::uno::UNO_QUERY
);
597 if ( xDataSource
.is() )
598 return lcl_getInteractionHandler_throw( xDataSource
, _rFallback
);
604 Reference
< XPropertySet
> CopyTableWizard::impl_ensureDataAccessDescriptor_throw(
605 const Sequence
< Any
>& _rAllArgs
, const sal_Int16 _nArgPos
, SharedConnection
& _out_rxConnection
,
606 Reference
< XInteractionHandler
>& _out_rxDocInteractionHandler
) const
608 Reference
< XPropertySet
> xDescriptor
;
609 _rAllArgs
[ _nArgPos
] >>= xDescriptor
;
611 // the descriptor must be non-NULL, of course
612 bool bIsValid
= xDescriptor
.is();
614 // it must support the proper service
617 Reference
< XServiceInfo
> xSI( xDescriptor
, UNO_QUERY
);
618 bIsValid
= ( xSI
.is()
619 && xSI
->supportsService( "com.sun.star.sdb.DataAccessDescriptor" ) );
622 // it must be able to provide a connection
625 _out_rxConnection
= impl_extractConnection_throw( xDescriptor
, _out_rxDocInteractionHandler
);
626 bIsValid
= _out_rxConnection
.is();
631 throw IllegalArgumentException(
632 DBA_RES( STR_CTW_INVALID_DATA_ACCESS_DESCRIPTOR
),
633 *const_cast< CopyTableWizard
* >( this ),
643 bool lcl_hasNonEmptyStringValue_throw( const Reference
< XPropertySet
>& _rxDescriptor
,
644 const Reference
< XPropertySetInfo
>& rxPSI
, const OUString
& _rPropertyName
)
647 if ( rxPSI
->hasPropertyByName( _rPropertyName
) )
649 OSL_VERIFY( _rxDescriptor
->getPropertyValue( _rPropertyName
) >>= sValue
);
651 return !sValue
.isEmpty();
655 void CopyTableWizard::impl_checkForUnsupportedSettings_throw( const Reference
< XPropertySet
>& _rxSourceDescriptor
) const
657 OSL_PRECOND( _rxSourceDescriptor
.is(), "CopyTableWizard::impl_checkForUnsupportedSettings_throw: illegal argument!" );
658 Reference
< XPropertySetInfo
> xPSI( _rxSourceDescriptor
->getPropertySetInfo(), UNO_SET_THROW
);
659 OUString sUnsupportedSetting
;
661 const OUString aSettings
[] = {
662 OUString(PROPERTY_FILTER
), OUString(PROPERTY_ORDER
), OUString(PROPERTY_HAVING_CLAUSE
), OUString(PROPERTY_GROUP_BY
)
664 for (const auto & aSetting
: aSettings
)
666 if ( lcl_hasNonEmptyStringValue_throw( _rxSourceDescriptor
, xPSI
, aSetting
) )
668 sUnsupportedSetting
= aSetting
;
673 if ( !sUnsupportedSetting
.isEmpty() )
676 DBA_RES(STR_CTW_ERROR_UNSUPPORTED_SETTING
).
677 replaceFirst("$name$", sUnsupportedSetting
));
678 throw IllegalArgumentException(
680 *const_cast< CopyTableWizard
* >( this ),
687 std::unique_ptr
< ICopyTableSourceObject
> CopyTableWizard::impl_extractSourceObject_throw( const Reference
< XPropertySet
>& _rxDescriptor
, sal_Int32
& _out_rCommandType
) const
689 OSL_PRECOND( _rxDescriptor
.is() && m_xSourceConnection
.is(), "CopyTableWizard::impl_extractSourceObject_throw: illegal arguments!" );
691 Reference
< XPropertySetInfo
> xPSI( _rxDescriptor
->getPropertySetInfo(), UNO_SET_THROW
);
692 if ( !xPSI
->hasPropertyByName( PROPERTY_COMMAND
)
693 || !xPSI
->hasPropertyByName( PROPERTY_COMMAND_TYPE
)
695 throw IllegalArgumentException("Expecting a table or query specification.",
697 *const_cast< CopyTableWizard
* >( this ), 1);
700 _out_rCommandType
= CommandType::COMMAND
;
701 OSL_VERIFY( _rxDescriptor
->getPropertyValue( PROPERTY_COMMAND
) >>= sCommand
);
702 OSL_VERIFY( _rxDescriptor
->getPropertyValue( PROPERTY_COMMAND_TYPE
) >>= _out_rCommandType
);
704 std::unique_ptr
< ICopyTableSourceObject
> pSourceObject
;
705 Reference
< XNameAccess
> xContainer
;
706 switch ( _out_rCommandType
)
708 case CommandType::TABLE
:
710 Reference
< XTablesSupplier
> xSuppTables( m_xSourceConnection
.getTyped(), UNO_QUERY
);
711 if ( xSuppTables
.is() )
712 xContainer
.set( xSuppTables
->getTables(), UNO_SET_THROW
);
715 case CommandType::QUERY
:
717 Reference
< XQueriesSupplier
> xSuppQueries( m_xSourceConnection
.getTyped(), UNO_QUERY
);
718 if ( xSuppQueries
.is() )
719 xContainer
.set( xSuppQueries
->getQueries(), UNO_SET_THROW
);
723 throw IllegalArgumentException(
724 DBA_RES( STR_CTW_ONLY_TABLES_AND_QUERIES_SUPPORT
),
725 *const_cast< CopyTableWizard
* >( this ),
730 if ( xContainer
.is() )
732 pSourceObject
.reset( new ObjectCopySource( m_xSourceConnection
,
733 Reference
< XPropertySet
>( xContainer
->getByName( sCommand
), UNO_QUERY_THROW
) ) );
737 // our source connection is an SDBC level connection only, not a SDBCX level one
738 // Which means it cannot provide the to-be-copied object as component.
740 if ( _out_rCommandType
== CommandType::QUERY
)
741 // we cannot copy a query if the connection cannot provide it ...
742 throw IllegalArgumentException(
743 DBA_RES( STR_CTW_ERROR_NO_QUERY
),
744 *const_cast< CopyTableWizard
* >( this ),
747 pSourceObject
.reset( new NamedTableCopySource( m_xSourceConnection
, sCommand
) );
750 return pSourceObject
;
753 void CopyTableWizard::impl_extractSourceResultSet_throw( const Reference
< XPropertySet
>& i_rDescriptor
)
755 Reference
< XPropertySetInfo
> xPSI( i_rDescriptor
->getPropertySetInfo(), UNO_SET_THROW
);
757 // extract relevant settings
758 if ( xPSI
->hasPropertyByName( PROPERTY_RESULT_SET
) )
759 m_xSourceResultSet
.set( i_rDescriptor
->getPropertyValue( PROPERTY_RESULT_SET
), UNO_QUERY
);
761 if ( xPSI
->hasPropertyByName( PROPERTY_SELECTION
) )
762 OSL_VERIFY( i_rDescriptor
->getPropertyValue( PROPERTY_SELECTION
) >>= m_aSourceSelection
);
764 if ( xPSI
->hasPropertyByName( PROPERTY_BOOKMARK_SELECTION
) )
765 OSL_VERIFY( i_rDescriptor
->getPropertyValue( PROPERTY_BOOKMARK_SELECTION
) >>= m_bSourceSelectionBookmarks
);
768 const bool bHasResultSet
= m_xSourceResultSet
.is();
769 const bool bHasSelection
= m_aSourceSelection
.hasElements();
770 if ( bHasSelection
&& !bHasResultSet
)
771 throw IllegalArgumentException("A result set is needed when specifying a selection to copy.",
775 if ( bHasSelection
&& m_bSourceSelectionBookmarks
)
777 Reference
< XRowLocate
> xRowLocate( m_xSourceResultSet
, UNO_QUERY
);
778 if ( !xRowLocate
.is() )
780 ::dbtools::throwGenericSQLException(
781 DBA_RES(STR_CTW_COPY_SOURCE_NEEDS_BOOKMARKS
),
788 SharedConnection
CopyTableWizard::impl_extractConnection_throw( const Reference
< XPropertySet
>& _rxDataSourceDescriptor
,
789 Reference
< XInteractionHandler
>& _out_rxDocInteractionHandler
) const
791 SharedConnection xConnection
;
793 OSL_PRECOND( _rxDataSourceDescriptor
.is(), "CopyTableWizard::impl_extractConnection_throw: no descriptor!" );
794 if ( !_rxDataSourceDescriptor
.is() )
797 Reference
< XInteractionHandler
> xInteractionHandler
;
801 Reference
< XPropertySetInfo
> xPSI( _rxDataSourceDescriptor
->getPropertySetInfo(), UNO_SET_THROW
);
803 // if there's an ActiveConnection, use it
804 if ( xPSI
->hasPropertyByName( PROPERTY_ACTIVE_CONNECTION
) )
806 Reference
< XConnection
> xPure
;
807 OSL_VERIFY( _rxDataSourceDescriptor
->getPropertyValue( PROPERTY_ACTIVE_CONNECTION
) >>= xPure
);
808 xConnection
.reset( xPure
, SharedConnection::NoTakeOwnership
);
810 if ( xConnection
.is() )
812 xInteractionHandler
= lcl_getInteractionHandler_throw( xConnection
.getTyped(), m_xInteractionHandler
);
813 SAL_WARN_IF( !xInteractionHandler
.is(), "dbaccess.ui", "CopyTableWizard::impl_extractConnection_throw: lcl_getInteractionHandler_throw returned nonsense!" );
817 // there could be a DataSourceName or a DatabaseLocation, describing the css.sdb.DataSource
818 OUString sDataSource
, sDatabaseLocation
;
819 if ( xPSI
->hasPropertyByName( PROPERTY_DATASOURCENAME
) )
820 OSL_VERIFY( _rxDataSourceDescriptor
->getPropertyValue( PROPERTY_DATASOURCENAME
) >>= sDataSource
);
821 if ( xPSI
->hasPropertyByName( PROPERTY_DATABASE_LOCATION
) )
822 OSL_VERIFY( _rxDataSourceDescriptor
->getPropertyValue( PROPERTY_DATABASE_LOCATION
) >>= sDatabaseLocation
);
824 // need a DatabaseContext for loading the data source
825 Reference
< XDatabaseContext
> xDatabaseContext
= DatabaseContext::create( m_xContext
);
826 Reference
< XDataSource
> xDataSource
;
827 if ( !sDataSource
.isEmpty() )
828 xDataSource
.set( xDatabaseContext
->getByName( sDataSource
), UNO_QUERY_THROW
);
829 if ( !xDataSource
.is() && !sDatabaseLocation
.isEmpty() )
830 xDataSource
.set( xDatabaseContext
->getByName( sDatabaseLocation
), UNO_QUERY_THROW
);
832 if ( xDataSource
.is() )
834 // first, try connecting with completion
835 xInteractionHandler
= lcl_getInteractionHandler_throw( xDataSource
, m_xInteractionHandler
);
836 SAL_WARN_IF( !xInteractionHandler
.is(), "dbaccess.ui", "CopyTableWizard::impl_extractConnection_throw: lcl_getInteractionHandler_throw returned nonsense!" );
837 if ( xInteractionHandler
.is() )
839 Reference
< XCompletedConnection
> xInteractiveConnection( xDataSource
, UNO_QUERY
);
840 if ( xInteractiveConnection
.is() )
841 xConnection
.reset( xInteractiveConnection
->connectWithCompletion( xInteractionHandler
), SharedConnection::TakeOwnership
);
844 // interactively connecting was not successful or possible -> connect without interaction
845 if ( !xConnection
.is() )
847 xConnection
.reset( xDataSource
->getConnection( OUString(), OUString() ), SharedConnection::TakeOwnership
);
851 if ( xConnection
.is() )
854 // finally, there could be a ConnectionResource/ConnectionInfo
855 OUString sConnectionResource
;
856 Sequence
< PropertyValue
> aConnectionInfo
;
857 if ( xPSI
->hasPropertyByName( PROPERTY_CONNECTION_RESOURCE
) )
858 OSL_VERIFY( _rxDataSourceDescriptor
->getPropertyValue( PROPERTY_CONNECTION_RESOURCE
) >>= sConnectionResource
);
859 if ( xPSI
->hasPropertyByName( PROPERTY_CONNECTION_INFO
) )
860 OSL_VERIFY( _rxDataSourceDescriptor
->getPropertyValue( PROPERTY_CONNECTION_INFO
) >>= aConnectionInfo
);
862 Reference
< XDriverManager
> xDriverManager
;
864 xDriverManager
.set( ConnectionPool::create( m_xContext
), UNO_QUERY_THROW
);
865 } catch( const Exception
& ) { }
866 if ( !xDriverManager
.is() )
867 // no connection pool installed
868 xDriverManager
.set( DriverManager::create( m_xContext
), UNO_QUERY_THROW
);
870 if ( aConnectionInfo
.hasElements() )
871 xConnection
.set( xDriverManager
->getConnectionWithInfo( sConnectionResource
, aConnectionInfo
), UNO_SET_THROW
);
873 xConnection
.set( xDriverManager
->getConnection( sConnectionResource
), UNO_SET_THROW
);
877 if ( xInteractionHandler
!= m_xInteractionHandler
)
878 _out_rxDocInteractionHandler
= xInteractionHandler
;
883 ::utl::SharedUNOComponent
< XPreparedStatement
> CopyTableWizard::impl_createSourceStatement_throw() const
885 OSL_PRECOND( m_xSourceConnection
.is(), "CopyTableWizard::impl_createSourceStatement_throw: illegal call!" );
886 if ( !m_xSourceConnection
.is() )
887 throw RuntimeException( "CopyTableWizard::impl_createSourceStatement_throw: illegal call!", *const_cast< CopyTableWizard
* >( this ));
889 ::utl::SharedUNOComponent
< XPreparedStatement
> xStatement
;
890 switch ( m_nCommandType
)
892 case CommandType::TABLE
:
893 xStatement
.set( m_pSourceObject
->getPreparedSelectStatement(), UNO_SET_THROW
);
896 case CommandType::QUERY
:
898 OUString
sQueryCommand( m_pSourceObject
->getSelectStatement() );
899 xStatement
.set( m_pSourceObject
->getPreparedSelectStatement(), UNO_SET_THROW
);
901 // check whether we have to fill in parameter values
902 // create and fill a composer
904 Reference
< XMultiServiceFactory
> xFactory( m_xSourceConnection
, UNO_QUERY
);
905 ::utl::SharedUNOComponent
< XSingleSelectQueryComposer
> xComposer
;
907 // note: connections below the sdb-level are allowed to not support the XMultiServiceFactory interface
908 xComposer
.set( xFactory
->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER
), UNO_QUERY
);
910 if ( xComposer
.is() )
912 xComposer
->setQuery( sQueryCommand
);
914 Reference
< XParameters
> xStatementParams( xStatement
, UNO_QUERY
);
915 OSL_ENSURE( xStatementParams
.is(), "CopyTableWizard::impl_createSourceStatement_throw: no access to the statement's parameters!" );
916 // the statement should be a css.sdbc.PreparedStatement (this is what
917 // we created), and a prepared statement is required to support XParameters
918 if ( xStatementParams
.is() )
920 OSL_ENSURE( m_xInteractionHandler
.is(),
921 "CopyTableWizard::impl_createSourceStatement_throw: no interaction handler for the parameters request!" );
922 // we should always have an interaction handler - as last fallback, we create an own one in ::initialize
924 if ( m_xInteractionHandler
.is() )
925 ::dbtools::askForParameters( xComposer
, xStatementParams
, m_xSourceConnection
, m_xInteractionHandler
);
932 // this should not have survived initialization phase
933 throw RuntimeException("No case matched, this should not have survived the initialization phase", *const_cast< CopyTableWizard
* >( this ));
944 ValueTransfer( std::vector
< sal_Int32
> _rColTypes
,
945 const Reference
< XRow
>& _rxSource
, const Reference
< XParameters
>& _rxDest
)
946 :m_ColTypes( std::move(_rColTypes
) )
947 ,m_xSource( _rxSource
)
952 template< typename VALUE_TYPE
>
953 void transferValue( sal_Int32 _nSourcePos
, sal_Int32 _nDestPos
,
954 VALUE_TYPE ( SAL_CALL
XRow::*_pGetter
)( sal_Int32
),
955 void (SAL_CALL
XParameters::*_pSetter
)( sal_Int32
, VALUE_TYPE
) )
957 VALUE_TYPE
value( (m_xSource
.get()->*_pGetter
)( _nSourcePos
) );
958 if ( m_xSource
->wasNull() )
959 m_xDest
->setNull( _nDestPos
, m_ColTypes
[ _nSourcePos
] );
961 (m_xDest
.get()->*_pSetter
)( _nDestPos
, value
);
964 template< typename VALUE_TYPE
>
965 void transferComplexValue( sal_Int32 _nSourcePos
, sal_Int32 _nDestPos
,
966 VALUE_TYPE ( SAL_CALL
XRow::*_pGetter
)( sal_Int32
),
967 void (SAL_CALL
XParameters::*_pSetter
)( sal_Int32
, const VALUE_TYPE
& ) )
969 const VALUE_TYPE
value( (m_xSource
.get()->*_pGetter
)( _nSourcePos
) );
970 if ( m_xSource
->wasNull() )
971 m_xDest
->setNull( _nDestPos
, m_ColTypes
[ _nSourcePos
] );
973 (m_xDest
.get()->*_pSetter
)( _nDestPos
, value
);
976 const std::vector
< sal_Int32
> m_ColTypes
;
977 const Reference
< XRow
> m_xSource
;
978 const Reference
< XParameters
> m_xDest
;
982 bool CopyTableWizard::impl_processCopyError_nothrow( const CopyTableRowEvent
& _rEvent
)
986 ::comphelper::OInterfaceIteratorHelper3
aIter( m_aCopyTableListeners
);
987 while ( aIter
.hasMoreElements() )
989 Reference
< XCopyTableListener
> xListener( aIter
.next() );
990 sal_Int16 nListenerChoice
= xListener
->copyRowError( _rEvent
);
991 switch ( nListenerChoice
)
993 case CopyTableContinuation::Proceed
: return true; // continue copying
994 case CopyTableContinuation::CallNextHandler
: continue; // continue the loop, ask next listener
995 case CopyTableContinuation::Cancel
: return false; // cancel copying
996 case CopyTableContinuation::AskUser
: break; // stop asking the listeners, ask the user
999 SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_processCopyError_nothrow: invalid listener response!" );
1000 // ask next listener
1005 catch( const Exception
& )
1007 DBG_UNHANDLED_EXCEPTION("dbaccess");
1010 // no listener felt responsible for the error, or a listener told to ask the user
1015 aError
.Context
= *this;
1016 aError
.Message
= DBA_RES(STR_ERROR_OCCURRED_WHILE_COPYING
);
1018 ::dbtools::SQLExceptionInfo
aInfo( _rEvent
.Error
);
1019 if ( aInfo
.isValid() )
1020 aError
.NextException
= _rEvent
.Error
;
1023 // a non-SQL exception happened
1024 Exception aException
;
1025 OSL_VERIFY( _rEvent
.Error
>>= aException
);
1026 SQLContext aContext
;
1027 aContext
.Context
= aException
.Context
;
1028 aContext
.Message
= aException
.Message
;
1029 aContext
.Details
= _rEvent
.Error
.getValueTypeName();
1030 aError
.NextException
<<= aContext
;
1033 ::rtl::Reference
< ::comphelper::OInteractionRequest
> xRequest( new ::comphelper::OInteractionRequest( Any( aError
) ) );
1035 ::rtl::Reference
< ::comphelper::OInteractionApprove
> xYes
= new ::comphelper::OInteractionApprove
;
1036 xRequest
->addContinuation( xYes
);
1037 xRequest
->addContinuation( new ::comphelper::OInteractionDisapprove
);
1039 OSL_ENSURE( m_xInteractionHandler
.is(),
1040 "CopyTableWizard::impl_processCopyError_nothrow: we always should have an interaction handler!" );
1041 if ( m_xInteractionHandler
.is() )
1042 m_xInteractionHandler
->handle( xRequest
);
1044 if ( xYes
->wasSelected() )
1048 catch( const Exception
& )
1050 DBG_UNHANDLED_EXCEPTION("dbaccess");
1057 void CopyTableWizard::impl_copyRows_throw( const Reference
< XResultSet
>& _rxSourceResultSet
,
1058 const Reference
< XPropertySet
>& _rxDestTable
)
1060 OSL_PRECOND( m_xDestConnection
.is(), "CopyTableWizard::impl_copyRows_throw: illegal call!" );
1061 if ( !m_xDestConnection
.is() )
1062 throw RuntimeException( "m_xDestConnection is set to null, CopyTableWizard::impl_copyRows_throw: illegal call!", *this );
1064 Reference
< XDatabaseMetaData
> xDestMetaData( m_xDestConnection
->getMetaData(), UNO_SET_THROW
);
1066 const OCopyTableWizard
& rWizard
= impl_getDialog_throw();
1067 ODatabaseExport::TPositions aColumnPositions
= rWizard
.GetColumnPositions();
1068 const bool bShouldCreatePrimaryKey
= rWizard
.shouldCreatePrimaryKey();
1070 Reference
< XRow
> xRow ( _rxSourceResultSet
, UNO_QUERY_THROW
);
1071 Reference
< XRowLocate
> xRowLocate ( _rxSourceResultSet
, UNO_QUERY_THROW
);
1073 Reference
< XResultSetMetaDataSupplier
> xSuppResMeta( _rxSourceResultSet
, UNO_QUERY_THROW
);
1074 Reference
< XResultSetMetaData
> xMeta( xSuppResMeta
->getMetaData() );
1076 // we need a vector which all types
1077 sal_Int32 nCount
= xMeta
->getColumnCount();
1078 std::vector
< sal_Int32
> aSourceColTypes
;
1079 aSourceColTypes
.reserve( nCount
+ 1 );
1080 aSourceColTypes
.push_back( -1 ); // just to avoid an every time i-1 call
1082 std::vector
< sal_Int32
> aSourcePrec
;
1083 aSourcePrec
.reserve( nCount
+ 1 );
1084 aSourcePrec
.push_back( -1 ); // just to avoid an every time i-1 call
1086 for ( sal_Int32 k
=1; k
<= nCount
; ++k
)
1088 aSourceColTypes
.push_back( xMeta
->getColumnType( k
) );
1089 aSourcePrec
.push_back( xMeta
->getPrecision( k
) );
1092 // now create, fill and execute the prepared statement
1093 Reference
< XPreparedStatement
> xStatement( ODatabaseExport::createPreparedStatement( xDestMetaData
, _rxDestTable
, aColumnPositions
), UNO_SET_THROW
);
1094 Reference
< XParameters
> xStatementParams( xStatement
, UNO_QUERY_THROW
);
1096 const bool bSelectedRecordsOnly
= m_aSourceSelection
.hasElements();
1097 const Any
* pSelectedRow
= m_aSourceSelection
.getConstArray();
1098 const Any
* pSelEnd
= pSelectedRow
+ m_aSourceSelection
.getLength();
1100 sal_Int32 nRowCount
= 0;
1101 bool bContinue
= false;
1103 CopyTableRowEvent aCopyEvent
;
1104 aCopyEvent
.Source
= *this;
1105 aCopyEvent
.SourceData
= _rxSourceResultSet
;
1107 do // loop as long as there are more rows or the selection ends
1110 if ( bSelectedRecordsOnly
)
1112 if ( pSelectedRow
!= pSelEnd
)
1114 if ( m_bSourceSelectionBookmarks
)
1116 bContinue
= xRowLocate
->moveToBookmark( *pSelectedRow
);
1121 OSL_VERIFY( *pSelectedRow
>>= nPos
);
1122 bContinue
= _rxSourceResultSet
->absolute( nPos
);
1128 bContinue
= _rxSourceResultSet
->next();
1137 aCopyEvent
.Error
.clear();
1140 bool bInsertedPrimaryKey
= false;
1142 m_aCopyTableListeners
.notifyEach( &XCopyTableListener::copyingRow
, aCopyEvent
);
1144 sal_Int32
nSourceColumn( 1 );
1145 ValueTransfer
aTransfer( aSourceColTypes
, xRow
, xStatementParams
);
1147 for ( auto const& rColumnPos
: aColumnPositions
)
1149 sal_Int32 nDestColumn
= rColumnPos
.first
;
1150 if ( nDestColumn
== COLUMN_POSITION_NOT_FOUND
)
1153 // otherwise we don't get the correct value when only the 2nd source column was selected
1157 if ( bShouldCreatePrimaryKey
&& !bInsertedPrimaryKey
)
1159 xStatementParams
->setInt( 1, nRowCount
);
1161 bInsertedPrimaryKey
= true;
1165 if ( ( nSourceColumn
< 1 ) || ( o3tl::make_unsigned(nSourceColumn
) >= aSourceColTypes
.size() ) )
1166 { // ( we have to check here against 1 because the parameters are 1 based)
1167 ::dbtools::throwSQLException("Internal error: invalid column type index.",
1168 ::dbtools::StandardSQLState::INVALID_DESCRIPTOR_INDEX
, *this);
1171 switch ( aSourceColTypes
[ nSourceColumn
] )
1173 case DataType::DOUBLE
:
1174 case DataType::REAL
:
1175 aTransfer
.transferValue( nSourceColumn
, nDestColumn
, &XRow::getDouble
, &XParameters::setDouble
);
1178 case DataType::CHAR
:
1179 case DataType::VARCHAR
:
1180 case DataType::LONGVARCHAR
:
1181 case DataType::DECIMAL
:
1182 case DataType::NUMERIC
:
1183 aTransfer
.transferComplexValue( nSourceColumn
, nDestColumn
, &XRow::getString
, &XParameters::setString
);
1186 case DataType::BIGINT
:
1187 aTransfer
.transferValue( nSourceColumn
, nDestColumn
, &XRow::getLong
, &XParameters::setLong
);
1190 case DataType::FLOAT
:
1191 aTransfer
.transferValue( nSourceColumn
, nDestColumn
, &XRow::getFloat
, &XParameters::setFloat
);
1194 case DataType::LONGVARBINARY
:
1195 case DataType::BINARY
:
1196 case DataType::VARBINARY
:
1197 aTransfer
.transferComplexValue( nSourceColumn
, nDestColumn
, &XRow::getBytes
, &XParameters::setBytes
);
1200 case DataType::DATE
:
1201 aTransfer
.transferComplexValue( nSourceColumn
, nDestColumn
, &XRow::getDate
, &XParameters::setDate
);
1204 case DataType::TIME
:
1205 aTransfer
.transferComplexValue( nSourceColumn
, nDestColumn
, &XRow::getTime
, &XParameters::setTime
);
1208 case DataType::TIMESTAMP
:
1209 aTransfer
.transferComplexValue( nSourceColumn
, nDestColumn
, &XRow::getTimestamp
, &XParameters::setTimestamp
);
1213 if ( aSourcePrec
[nSourceColumn
] > 1 )
1215 aTransfer
.transferComplexValue( nSourceColumn
, nDestColumn
, &XRow::getBytes
, &XParameters::setBytes
);
1219 case DataType::BOOLEAN
:
1220 aTransfer
.transferValue( nSourceColumn
, nDestColumn
, &XRow::getBoolean
, &XParameters::setBoolean
);
1223 case DataType::TINYINT
:
1224 aTransfer
.transferValue( nSourceColumn
, nDestColumn
, &XRow::getByte
, &XParameters::setByte
);
1227 case DataType::SMALLINT
:
1228 aTransfer
.transferValue( nSourceColumn
, nDestColumn
, &XRow::getShort
, &XParameters::setShort
);
1231 case DataType::INTEGER
:
1232 aTransfer
.transferValue( nSourceColumn
, nDestColumn
, &XRow::getInt
, &XParameters::setInt
);
1235 case DataType::BLOB
:
1236 aTransfer
.transferComplexValue( nSourceColumn
, nDestColumn
, &XRow::getBlob
, &XParameters::setBlob
);
1239 case DataType::CLOB
:
1240 aTransfer
.transferComplexValue( nSourceColumn
, nDestColumn
, &XRow::getClob
, &XParameters::setClob
);
1245 OUString
aMessage( DBA_RES( STR_CTW_UNSUPPORTED_COLUMN_TYPE
) );
1247 aMessage
= aMessage
.replaceFirst( "$type$", OUString::number( aSourceColTypes
[ nSourceColumn
] ) );
1248 aMessage
= aMessage
.replaceFirst( "$pos$", OUString::number( nSourceColumn
) );
1250 ::dbtools::throwSQLException(
1252 ::dbtools::StandardSQLState::INVALID_SQL_DATA_TYPE
,
1259 xStatement
->executeUpdate();
1262 m_aCopyTableListeners
.notifyEach( &XCopyTableListener::copiedRow
, aCopyEvent
);
1264 catch( const Exception
& )
1266 TOOLS_WARN_EXCEPTION("dbaccess", "");
1267 aCopyEvent
.Error
= ::cppu::getCaughtException();
1270 if ( aCopyEvent
.Error
.hasValue() )
1271 bContinue
= impl_processCopyError_nothrow( aCopyEvent
);
1276 void CopyTableWizard::impl_doCopy_nothrow()
1282 OCopyTableWizard
& rWizard( impl_getDialog_throw() );
1284 weld::WaitObject
aWO(rWizard
.getDialog());
1285 Reference
< XPropertySet
> xTable
;
1287 switch ( rWizard
.getOperation() )
1289 case CopyTableOperation::CopyDefinitionOnly
:
1290 case CopyTableOperation::CopyDefinitionAndData
:
1292 xTable
= rWizard
.createTable();
1296 SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_doCopy_nothrow: createTable should throw here, shouldn't it?" );
1300 if( CopyTableOperation::CopyDefinitionOnly
== rWizard
.getOperation() )
1306 case CopyTableOperation::AppendData
:
1308 // note that the CopyDefinitionAndData case falls through to here.
1309 assert((rWizard
.getOperation() == CopyTableOperation::CopyDefinitionAndData
) ||
1310 (rWizard
.getOperation() == CopyTableOperation::AppendData
));
1311 assert((rWizard
.getOperation() == CopyTableOperation::CopyDefinitionAndData
) == xTable
.is());
1314 assert(rWizard
.getOperation() == CopyTableOperation::AppendData
);
1315 xTable
= rWizard
.getTable();
1318 SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_doCopy_nothrow: getTable should throw here, shouldn't it?" );
1323 ::utl::SharedUNOComponent
< XPreparedStatement
> xSourceStatement
;
1324 ::utl::SharedUNOComponent
< XResultSet
> xSourceResultSet
;
1326 if ( m_xSourceResultSet
.is() )
1328 xSourceResultSet
.reset( m_xSourceResultSet
, ::utl::SharedUNOComponent
< XResultSet
>::NoTakeOwnership
);
1332 const bool bIsSameConnection
= ( m_xSourceConnection
.getTyped() == m_xDestConnection
.getTyped() );
1333 const bool bIsTable
= ( CommandType::TABLE
== m_nCommandType
);
1335 if ( bIsSameConnection
&& bIsTable
)
1337 // try whether the server supports copying via SQL
1340 m_xDestConnection
->createStatement()->executeUpdate( impl_getServerSideCopyStatement_throw(xTable
) );
1343 catch( const Exception
& )
1351 xSourceStatement
.set( impl_createSourceStatement_throw(), UNO_SET_THROW
);
1352 xSourceResultSet
.set( xSourceStatement
->executeQuery(), UNO_SET_THROW
);
1356 if ( xSourceResultSet
.is() )
1357 impl_copyRows_throw( xSourceResultSet
, xTable
);
1360 const Reference
< XDatabaseMetaData
> xDestMetaData( m_xDestConnection
->getMetaData(), UNO_SET_THROW
);
1361 OUString sDatabaseDest
= xDestMetaData
->getDatabaseProductName().toAsciiLowerCase();
1362 // If we created a new primary key, then it won't necessarily be an IDENTITY column
1363 const bool bShouldCreatePrimaryKey
= rWizard
.shouldCreatePrimaryKey();
1364 if ( !bShouldCreatePrimaryKey
&& (sDatabaseDest
.indexOf("firebird") != -1) )
1366 const OUString sComposedTableName
= ::dbtools::composeTableName( xDestMetaData
, xTable
, ::dbtools::EComposeRule::InDataManipulation
, true );
1368 OUString aSchema
,aTable
;
1369 xTable
->getPropertyValue("SchemaName") >>= aSchema
;
1370 xTable
->getPropertyValue("Name") >>= aTable
;
1371 Any aCatalog
= xTable
->getPropertyValue("CatalogName");
1373 const Reference
< XResultSet
> xResultPKCL(xDestMetaData
->getPrimaryKeys(aCatalog
,aSchema
,aTable
));
1374 Reference
< XRow
> xRowPKCL(xResultPKCL
, UNO_QUERY_THROW
);
1376 if ( xRowPKCL
.is() )
1378 if (xResultPKCL
->next())
1380 sPKCL
= xRowPKCL
->getString(4);
1384 if (!sPKCL
.isEmpty())
1386 OUString strSql
= "SELECT MAX(\"" + sPKCL
+ "\") FROM " + sComposedTableName
;
1388 Reference
< XResultSet
> xResultMAXNUM(m_xDestConnection
->createStatement()->executeQuery(strSql
));
1389 Reference
< XRow
> xRow(xResultMAXNUM
, UNO_QUERY_THROW
);
1391 sal_Int64 maxVal
= -1L;
1392 if (xResultMAXNUM
->next())
1394 maxVal
= xRow
->getLong(1);
1399 strSql
= "ALTER TABLE " + sComposedTableName
+ " ALTER \"" + sPKCL
+ "\" RESTART WITH " + OUString::number(maxVal
+ 1);
1401 m_xDestConnection
->createStatement()->execute(strSql
);
1408 case CopyTableOperation::CreateAsView
:
1409 rWizard
.createView();
1413 SAL_WARN("dbaccess.ui", "CopyTableWizard::impl_doCopy_nothrow: What operation, please?" );
1417 catch( const Exception
& )
1419 aError
= ::cppu::getCaughtException();
1420 SAL_WARN("dbaccess", exceptionToString(aError
));
1422 // silence the error of the user cancelling the parameter's dialog
1423 SQLException aSQLError
;
1424 if ( ( aError
>>= aSQLError
) && ( aSQLError
.ErrorCode
== ::dbtools::ParameterInteractionCancelled
) )
1427 m_nOverrideExecutionResult
= RET_CANCEL
;
1431 if ( aError
.hasValue() && m_xInteractionHandler
.is() )
1435 ::rtl::Reference
< ::comphelper::OInteractionRequest
> xRequest( new ::comphelper::OInteractionRequest( aError
) );
1436 m_xInteractionHandler
->handle( xRequest
);
1438 catch( const Exception
& )
1440 DBG_UNHANDLED_EXCEPTION("dbaccess");
1445 OUString
CopyTableWizard::impl_getServerSideCopyStatement_throw(const Reference
< XPropertySet
>& _xTable
)
1447 const Reference
<XColumnsSupplier
> xDestColsSup(_xTable
,UNO_QUERY_THROW
);
1448 const Sequence
< OUString
> aDestColumnNames
= xDestColsSup
->getColumns()->getElementNames();
1449 const Reference
< XDatabaseMetaData
> xDestMetaData( m_xDestConnection
->getMetaData(), UNO_SET_THROW
);
1450 const OUString sQuote
= xDestMetaData
->getIdentifierQuoteString();
1451 OUStringBuffer sColumns
;
1452 // 1st check if the columns matching
1453 for ( auto const & rColumnPositionPair
: impl_getDialog_throw().GetColumnPositions() )
1455 if ( COLUMN_POSITION_NOT_FOUND
!= rColumnPositionPair
.second
)
1457 if ( !sColumns
.isEmpty() )
1458 sColumns
.append(",");
1459 sColumns
.append(sQuote
+ aDestColumnNames
[rColumnPositionPair
.second
- 1] + sQuote
);
1462 const OUString sComposedTableName
= ::dbtools::composeTableName( xDestMetaData
, _xTable
, ::dbtools::EComposeRule::InDataManipulation
, true );
1463 OUString
sSql("INSERT INTO " + sComposedTableName
+ " ( " + sColumns
+ " ) " + m_pSourceObject
->getSelectStatement());
1468 void SAL_CALL
CopyTableWizard::initialize( const Sequence
< Any
>& _rArguments
)
1470 ::osl::MutexGuard
aGuard( m_aMutex
);
1471 if ( isInitialized() )
1472 throw AlreadyInitializedException( OUString(), *this );
1474 sal_Int32
nArgCount( _rArguments
.getLength() );
1475 if ( ( nArgCount
!= 2 ) && ( nArgCount
!= 3 ) )
1476 throw IllegalArgumentException(
1477 DBA_RES( STR_CTW_ILLEGAL_PARAMETER_COUNT
),
1484 if ( nArgCount
== 3 )
1485 { // ->createWithInteractionHandler
1486 if ( !( _rArguments
[2] >>= m_xInteractionHandler
) )
1487 throw IllegalArgumentException(
1488 DBA_RES( STR_CTW_ERROR_INVALID_INTERACTIONHANDLER
),
1493 if ( !m_xInteractionHandler
.is() )
1494 m_xInteractionHandler
= InteractionHandler::createWithParent(m_xContext
, nullptr);
1496 Reference
< XInteractionHandler
> xSourceDocHandler
;
1497 Reference
< XPropertySet
> xSourceDescriptor( impl_ensureDataAccessDescriptor_throw( _rArguments
, 0, m_xSourceConnection
, xSourceDocHandler
) );
1498 impl_checkForUnsupportedSettings_throw( xSourceDescriptor
);
1499 m_pSourceObject
= impl_extractSourceObject_throw( xSourceDescriptor
, m_nCommandType
);
1500 impl_extractSourceResultSet_throw( xSourceDescriptor
);
1502 Reference
< XInteractionHandler
> xDestDocHandler
;
1503 impl_ensureDataAccessDescriptor_throw( _rArguments
, 1, m_xDestConnection
, xDestDocHandler
);
1505 if ( xDestDocHandler
.is() && !m_xInteractionHandler
.is() )
1506 m_xInteractionHandler
= xDestDocHandler
;
1508 Reference
< XPropertySet
> xInteractionHandler(m_xInteractionHandler
, UNO_QUERY
);
1509 if (xInteractionHandler
.is())
1511 Any
aParentWindow(xInteractionHandler
->getPropertyValue("ParentWindow"));
1512 aParentWindow
>>= m_xParent
;
1515 catch( const RuntimeException
& ) { throw; }
1516 catch( const SQLException
& ) { throw; }
1517 catch( const Exception
& )
1519 throw WrappedTargetException(
1520 DBA_RES( STR_CTW_ERROR_DURING_INITIALIZATION
),
1522 ::cppu::getCaughtException()
1527 ::cppu::IPropertyArrayHelper
& CopyTableWizard::getInfoHelper()
1529 return *getArrayHelper();
1532 ::cppu::IPropertyArrayHelper
* CopyTableWizard::createArrayHelper( ) const
1534 Sequence
< Property
> aProps
;
1535 describeProperties( aProps
);
1536 return new ::cppu::OPropertyArrayHelper( aProps
);
1539 std::unique_ptr
<weld::DialogController
> CopyTableWizard::createDialog(const css::uno::Reference
<css::awt::XWindow
>& rParent
)
1541 OSL_PRECOND( isInitialized(), "CopyTableWizard::createDialog: not initialized!" );
1542 // this should have been prevented in ::execute already
1544 auto xWizard
= std::make_unique
<OCopyTableWizard
>(
1545 Application::GetFrameWeld(rParent
),
1546 m_sDestinationTable
,
1549 m_xSourceConnection
.getTyped(),
1550 m_xDestConnection
.getTyped(),
1552 m_xInteractionHandler
);
1554 impl_attributesToDialog_nothrow(*xWizard
);
1559 void CopyTableWizard::executedDialog( sal_Int16 _nExecutionResult
)
1561 CopyTableWizard_DialogBase::executedDialog( _nExecutionResult
);
1563 if ( _nExecutionResult
== RET_OK
)
1564 impl_doCopy_nothrow();
1566 // do this after impl_doCopy_nothrow: The attributes may change during copying, for instance
1567 // if the user entered an unqualified table name
1568 impl_dialogToAttributes_nothrow( impl_getDialog_throw() );
1571 } // namespace dbaui
1573 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
1574 org_openoffice_comp_dbu_CopyTableWizard_get_implementation(
1575 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const& )
1577 return cppu::acquire(new ::dbaui::CopyTableWizard(context
));
1580 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */