using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::XInterface; using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::UNO_QUERY_THROW; using ::com::sun::star::uno::UNO_SET_THROW; using ::com::sun::star::uno::Exception; using ::com::sun::star::uno::RuntimeException; using ::com::sun::star::uno::Any; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::XComponentContext; using ::com::sun::star::beans::XPropertySetInfo; using ::com::sun::star::lang::XMultiServiceFactory; using ::com::sun::star::beans::Property; using ::com::sun::star::sdb::application::XCopyTableWizard; using ::com::sun::star::sdb::application::XCopyTableListener; using ::com::sun::star::sdb::application::CopyTableRowEvent; using ::com::sun::star::beans::Optional; using ::com::sun::star::lang::IllegalArgumentException; using ::com::sun::star::ucb::AlreadyInitializedException; using ::com::sun::star::beans::XPropertySet; using ::com::sun::star::lang::NotInitializedException; using ::com::sun::star::lang::XServiceInfo; using ::com::sun::star::sdbc::XConnection; using ::com::sun::star::sdbc::XDataSource; using ::com::sun::star::container::XNameAccess; using ::com::sun::star::container::XChild; using ::com::sun::star::task::InteractionHandler; using ::com::sun::star::task::XInteractionHandler; using ::com::sun::star::frame::XModel; using ::com::sun::star::sdb::DatabaseContext; using ::com::sun::star::sdb::XDatabaseContext; using ::com::sun::star::sdb::XDocumentDataSource; using ::com::sun::star::sdb::XCompletedConnection; using ::com::sun::star::lang::WrappedTargetException; using ::com::sun::star::sdbcx::XTablesSupplier; using ::com::sun::star::sdb::XQueriesSupplier; using ::com::sun::star::lang::DisposedException; using ::com::sun::star::sdbc::XPreparedStatement; using ::com::sun::star::sdb::XSingleSelectQueryComposer; using ::com::sun::star::sdbc::XDatabaseMetaData; using ::com::sun::star::sdbcx::XColumnsSupplier; using ::com::sun::star::sdbc::XParameters; using ::com::sun::star::sdbc::XResultSet; using ::com::sun::star::sdbc::XRow; using ::com::sun::star::sdbcx::XRowLocate; using ::com::sun::star::sdbc::XResultSetMetaDataSupplier; using ::com::sun::star::sdbc::XResultSetMetaData; using ::com::sun::star::sdbc::SQLException; using ::com::sun::star::sdb::SQLContext; using ::com::sun::star::sdbc::ConnectionPool; using ::com::sun::star::sdbc::XDriverManager; using ::com::sun::star::sdbc::DriverManager; using ::com::sun::star::beans::PropertyValue;
private: /// ensures our current attribute values are reflected in the dialog void impl_attributesToDialog_nothrow( OCopyTableWizard& _rDialog ) const;
/// ensures the current dialog settings are reflected in our attributes void impl_dialogToAttributes_nothrow( const OCopyTableWizard& _rDialog );
/** ensures the given argument sequence contains a valid data access descriptor at the given position @param_rAllArgs theargumentsaspassedto->initialize @param_nArgPos thepositionwithin->_rAllArgswhichcontainsthedataaccessdescriptor @param_out_rxConnection will,uponsuccessfulreturn,containtheconnectionforthedatasource @param_out_rxDocInteractionHandler will,uponsuccessfulreturn,containtheinteractionhandlerwhichcould bededucedfromdatabasedocumentdescribedbythedescriptor,ifany. (Itispossiblethatthedescriptordoesnotallowtodeduceadatabasedocument, inwhichcase<code>_out_rxDocInteractionHandler</code>willbe<NULL/>.) @returnthedataaccessdescriptor
*/
Reference< XPropertySet >
impl_ensureDataAccessDescriptor_throw( const Sequence< Any >& _rAllArgs, const sal_Int16 _nArgPos,
SharedConnection& _out_rxConnection,
Reference< XInteractionHandler >& _out_rxDocInteractionHandler
) const;
/** extracts the source object (table or query) described by the given descriptor, relativetom_xSourceConnection
*/
std::unique_ptr< ICopyTableSourceObject >
impl_extractSourceObject_throw( const Reference< XPropertySet >& _rxDescriptor,
sal_Int32& _out_rCommandType
) const;
/** extracts the result set to copy records from, and the selection-related aspects, if any.
/** copies the data rows from the given source result set to the given destination table
*/ void impl_copyRows_throw( const Reference< XResultSet >& _rxSourceResultSet, const Reference< XPropertySet >& _rxDestTable
);
/** processes an error which occurred during copying
// TODO: shouldn't we have explicit disposal support? If a listener is registered // at our instance, and perhaps holds this our instance by a hard ref, then we'll never // be destroyed. // However, adding XComponent support to the GenericUNODialog probably requires // some thinking - would it break existing clients which do not call a dispose, then?
}
// try to obtain the document model
Reference< XModel > xDocumentModel;
Reference< XDocumentDataSource > xDocDataSource( _rxDataSource, UNO_QUERY ); if ( xDocDataSource.is() )
xDocumentModel.set( xDocDataSource->getDatabaseDocument(), UNO_QUERY_THROW );
// see whether the document model can provide a handler if ( xDocumentModel.is() )
{
xHandler = ::comphelper::NamedValueCollection::getOrDefault( xDocumentModel->getArgs(), u"InteractionHandler", xHandler );
}
return xHandler;
} /** tries to obtain the InteractionHandler associated with a given connection
// the descriptor must be non-NULL, of course bool bIsValid = xDescriptor.is();
// it must support the proper service if ( bIsValid )
{
Reference< XServiceInfo > xSI( xDescriptor, UNO_QUERY );
bIsValid = ( xSI.is()
&& xSI->supportsService( u"com.sun.star.sdb.DataAccessDescriptor"_ustr ) );
}
// it must be able to provide a connection if ( bIsValid )
{
_out_rxConnection = impl_extractConnection_throw( xDescriptor, _out_rxDocInteractionHandler );
bIsValid = _out_rxConnection.is();
}
if ( !bIsValid )
{ throw IllegalArgumentException(
DBA_RES( STR_CTW_INVALID_DATA_ACCESS_DESCRIPTOR ),
*const_cast< CopyTableWizard* >( this ),
_nArgPos + 1
);
}
if ( xContainer.is() )
{
pSourceObject.reset( new ObjectCopySource( m_xSourceConnection,
Reference< XPropertySet >( xContainer->getByName( sCommand ), UNO_QUERY_THROW ) ) );
} else
{ // our source connection is an SDBC level connection only, not a SDBCX level one // Which means it cannot provide the to-be-copied object as component.
if ( _out_rCommandType == CommandType::QUERY ) // we cannot copy a query if the connection cannot provide it ... throw IllegalArgumentException(
DBA_RES( STR_CTW_ERROR_NO_QUERY ),
*const_cast< CopyTableWizard* >( this ), 1
);
pSourceObject.reset( new NamedTableCopySource( m_xSourceConnection, sCommand ) );
}
// sanity checks constbool bHasResultSet = m_xSourceResultSet.is(); constbool bHasSelection = m_aSourceSelection.hasElements(); if ( bHasSelection && !bHasResultSet ) throw IllegalArgumentException(u"A result set is needed when specifying a selection to copy."_ustr, // TODO: resource
*this, 1);
do
{
Reference< XPropertySetInfo > xPSI( _rxDataSourceDescriptor->getPropertySetInfo(), UNO_SET_THROW );
// if there's an ActiveConnection, use it if ( xPSI->hasPropertyByName( PROPERTY_ACTIVE_CONNECTION ) )
{
Reference< XConnection > xPure;
OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xPure );
xConnection.reset( xPure, SharedConnection::NoTakeOwnership );
} if ( xConnection.is() )
{
xInteractionHandler = lcl_getInteractionHandler_throw( xConnection.getTyped(), m_xInteractionHandler );
SAL_WARN_IF( !xInteractionHandler.is(), "dbaccess.ui", "CopyTableWizard::impl_extractConnection_throw: lcl_getInteractionHandler_throw returned nonsense!" ); break;
}
// there could be a DataSourceName or a DatabaseLocation, describing the css.sdb.DataSource
OUString sDataSource, sDatabaseLocation; if ( xPSI->hasPropertyByName( PROPERTY_DATASOURCENAME ) )
OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_DATASOURCENAME ) >>= sDataSource ); if ( xPSI->hasPropertyByName( PROPERTY_DATABASE_LOCATION ) )
OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_DATABASE_LOCATION ) >>= sDatabaseLocation );
// need a DatabaseContext for loading the data source
Reference< XDatabaseContext > xDatabaseContext = DatabaseContext::create( m_xContext );
Reference< XDataSource > xDataSource; if ( !sDataSource.isEmpty() )
xDataSource.set( xDatabaseContext->getByName( sDataSource ), UNO_QUERY_THROW ); if ( !xDataSource.is() && !sDatabaseLocation.isEmpty() )
xDataSource.set( xDatabaseContext->getByName( sDatabaseLocation ), UNO_QUERY_THROW );
if ( xDataSource.is() )
{ // first, try connecting with completion
xInteractionHandler = lcl_getInteractionHandler_throw( xDataSource, m_xInteractionHandler );
SAL_WARN_IF( !xInteractionHandler.is(), "dbaccess.ui", "CopyTableWizard::impl_extractConnection_throw: lcl_getInteractionHandler_throw returned nonsense!" ); if ( xInteractionHandler.is() )
{
Reference< XCompletedConnection > xInteractiveConnection( xDataSource, UNO_QUERY ); if ( xInteractiveConnection.is() )
xConnection.reset( xInteractiveConnection->connectWithCompletion( xInteractionHandler ), SharedConnection::TakeOwnership );
}
// interactively connecting was not successful or possible -> connect without interaction if ( !xConnection.is() )
{
xConnection.reset( xDataSource->getConnection( OUString(), OUString() ), SharedConnection::TakeOwnership );
}
}
if ( xConnection.is() ) break;
// finally, there could be a ConnectionResource/ConnectionInfo
OUString sConnectionResource;
Sequence< PropertyValue > aConnectionInfo; if ( xPSI->hasPropertyByName( PROPERTY_CONNECTION_RESOURCE ) )
OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_CONNECTION_RESOURCE ) >>= sConnectionResource ); if ( xPSI->hasPropertyByName( PROPERTY_CONNECTION_INFO ) )
OSL_VERIFY( _rxDataSourceDescriptor->getPropertyValue( PROPERTY_CONNECTION_INFO ) >>= aConnectionInfo );
// check whether we have to fill in parameter values // create and fill a composer
Reference< XMultiServiceFactory > xFactory( m_xSourceConnection, UNO_QUERY );
::utl::SharedUNOComponent< XSingleSelectQueryComposer > xComposer; if ( xFactory.is() ) // note: connections below the sdb-level are allowed to not support the XMultiServiceFactory interface
xComposer.set( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY );
if ( xComposer.is() )
{
xComposer->setQuery( sQueryCommand );
Reference< XParameters > xStatementParams( xStatement, UNO_QUERY );
OSL_ENSURE( xStatementParams.is(), "CopyTableWizard::impl_createSourceStatement_throw: no access to the statement's parameters!" ); // the statement should be a css.sdbc.PreparedStatement (this is what // we created), and a prepared statement is required to support XParameters if ( xStatementParams.is() )
{
OSL_ENSURE( m_xInteractionHandler.is(), "CopyTableWizard::impl_createSourceStatement_throw: no interaction handler for the parameters request!" ); // we should always have an interaction handler - as last fallback, we create an own one in ::initialize
default: // this should not have survived initialization phase throw RuntimeException(u"No case matched, this should not have survived the initialization phase"_ustr, *const_cast< CopyTableWizard* >( this ));
}
::rtl::Reference< ::comphelper::OInteractionApprove > xYes = new ::comphelper::OInteractionApprove;
xRequest->addContinuation( xYes );
xRequest->addContinuation( new ::comphelper::OInteractionDisapprove );
OSL_ENSURE( m_xInteractionHandler.is(), "CopyTableWizard::impl_processCopyError_nothrow: we always should have an interaction handler!" ); if ( m_xInteractionHandler.is() )
m_xInteractionHandler->handle( xRequest );
// we need a vector which all types
sal_Int32 nCount = xMeta->getColumnCount();
std::vector< sal_Int32 > aSourceColTypes;
aSourceColTypes.reserve( nCount + 1 );
aSourceColTypes.push_back( -1 ); // just to avoid an every time i-1 call
std::vector< sal_Int32 > aSourcePrec;
aSourcePrec.reserve( nCount + 1 );
aSourcePrec.push_back( -1 ); // just to avoid an every time i-1 call
for ( sal_Int32 k=1; k <= nCount; ++k )
{
aSourceColTypes.push_back( xMeta->getColumnType( k ) );
aSourcePrec.push_back( xMeta->getPrecision( k ) );
}
// now create, fill and execute the prepared statement
Reference< XPreparedStatement > xStatement( ODatabaseExport::createPreparedStatement( xDestMetaData, _rxDestTable, aColumnPositions ), UNO_SET_THROW );
Reference< XParameters > xStatementParams( xStatement, UNO_QUERY_THROW );
for ( autoconst& rColumnPos : aColumnPositions )
{
sal_Int32 nDestColumn = rColumnPos.first; if ( nDestColumn == COLUMN_POSITION_NOT_FOUND )
{
++nSourceColumn; // otherwise we don't get the correct value when only the 2nd source column was selected continue;
}
if ( ( nSourceColumn < 1 ) || ( o3tl::make_unsigned(nSourceColumn) >= aSourceColTypes.size() ) )
{ // ( we have to check here against 1 because the parameters are 1 based)
::dbtools::throwSQLException(u"Internal error: invalid column type index."_ustr,
::dbtools::StandardSQLState::INVALID_DESCRIPTOR_INDEX, *this);
}
switch ( aSourceColTypes[ nSourceColumn ] )
{ case DataType::DOUBLE: case DataType::REAL:
aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getDouble, &XParameters::setDouble ); break;
case DataType::CHAR: case DataType::VARCHAR: case DataType::LONGVARCHAR: case DataType::DECIMAL: case DataType::NUMERIC:
aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getString, &XParameters::setString ); break;
case DataType::BIGINT:
aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getLong, &XParameters::setLong ); break;
case DataType::FLOAT:
aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getFloat, &XParameters::setFloat ); break;
case DataType::LONGVARBINARY: case DataType::BINARY: case DataType::VARBINARY:
aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getBytes, &XParameters::setBytes ); break;
case DataType::DATE:
aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getDate, &XParameters::setDate ); break;
case DataType::TIME:
aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getTime, &XParameters::setTime ); break;
case DataType::TIMESTAMP:
aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getTimestamp, &XParameters::setTimestamp ); break;
case DataType::BIT: if ( aSourcePrec[nSourceColumn] > 1 )
{
aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getBytes, &XParameters::setBytes ); break;
}
[[fallthrough]]; case DataType::BOOLEAN:
aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getBoolean, &XParameters::setBoolean ); break;
case DataType::TINYINT:
aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getByte, &XParameters::setByte ); break;
case DataType::SMALLINT:
aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getShort, &XParameters::setShort ); break;
case DataType::INTEGER:
aTransfer.transferValue( nSourceColumn, nDestColumn, &XRow::getInt, &XParameters::setInt ); break;
case DataType::BLOB:
aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getBlob, &XParameters::setBlob ); break;
case DataType::CLOB:
aTransfer.transferComplexValue( nSourceColumn, nDestColumn, &XRow::getClob, &XParameters::setClob ); break;
std::unique_ptr<weld::DialogController> CopyTableWizard::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
{
OSL_PRECOND( isInitialized(), "CopyTableWizard::createDialog: not initialized!" ); // this should have been prevented in ::execute already
if ( _nExecutionResult == RET_OK )
impl_doCopy_nothrow();
// do this after impl_doCopy_nothrow: The attributes may change during copying, for instance // if the user entered an unqualified table name
impl_dialogToAttributes_nothrow( impl_getDialog_throw() );
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.