/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
case PROPERTY_ID_DATASOURCENAME: if(!m_xStatement.is())
{
Reference< XConnection > xNewConn;
Any aNewConn;
aNewConn <<= xNewConn;
setFastPropertyValue(PROPERTY_ID_ACTIVE_CONNECTION, aNewConn);
} else
m_bRebuildConnOnExecute = true; break; case PROPERTY_ID_FETCHSIZE: if(m_pCache)
{
m_pCache->setFetchSize(m_nFetchSize);
fireRowcount();
} break; case PROPERTY_ID_URL: // is the connection-to-be-built determined by the url (which is the case if m_aDataSourceName is empty) ? if (m_aDataSourceName.isEmpty())
{ // are we active at the moment ? if (m_xStatement.is()) // yes -> the next execute needs to rebuild our connection because of this new property
m_bRebuildConnOnExecute = true; else
{ // no -> drop our active connection (if we have one) as it doesn't correspond to this new property value anymore
Reference< XConnection > xNewConn;
Any aNewConn;
aNewConn <<= xNewConn;
setFastPropertyValue(PROPERTY_ID_ACTIVE_CONNECTION, aNewConn);
}
}
m_bOwnConnection = true; break; case PROPERTY_ID_TYPEMAP:
m_xTypeMap.set(m_aTypeMap, css::uno::UNO_QUERY); break; case PROPERTY_ID_PROPCHANGE_NOTIFY:
m_bPropChangeNotifyEnabled = ::cppu::any2bool(rValue); break; default: break;
}
}
void SAL_CALL ORowSet::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const
{ if(m_pCache)
{ switch(nHandle)
{ case PROPERTY_ID_ISMODIFIED:
rValue <<= m_bModified; break; case PROPERTY_ID_ISNEW:
rValue <<= m_bNew; break; case PROPERTY_ID_PRIVILEGES:
rValue <<= m_pCache->m_nPrivileges; break; case PROPERTY_ID_ACTIVE_CONNECTION:
rValue <<= m_xActiveConnection; break; case PROPERTY_ID_TYPEMAP:
rValue <<= m_xTypeMap; break; default:
ORowSetBase::getFastPropertyValue(rValue,nHandle);
}
} else
{ switch(nHandle)
{ case PROPERTY_ID_ACTIVE_CONNECTION:
rValue <<= m_xActiveConnection; break; case PROPERTY_ID_TYPEMAP:
rValue <<= m_xTypeMap; break; case PROPERTY_ID_PROPCHANGE_NOTIFY:
rValue <<= m_bPropChangeNotifyEnabled; break; default:
ORowSetBase::getFastPropertyValue(rValue,nHandle);
}
}
}
// remove myself as dispose listener
Reference< XComponent > xComponent(m_xActiveConnection, UNO_QUERY); if (xComponent.is())
xComponent->removeEventListener(query_aggregation<XEventListener>(this));
m_aActiveConnection = Any(); // the any contains a reference too if(m_bOwnConnection)
::comphelper::disposeComponent(m_xActiveConnection);
m_xActiveConnection = nullptr;
// the columns must be disposed before the querycomposer is disposed because // their owner can be the composer
TDataColumns().swap(m_aDataColumns);// clear and resize capacity
std::vector<bool>().swap(m_aReadOnlyDataColumns);
m_xColumns = nullptr; if ( m_pColumns )
m_pColumns->disposing(); // dispose the composer to avoid that everybody knows that the querycomposer is eol try { ::comphelper::disposeComponent( m_xComposer ); } catch(Exception&)
{
DBG_UNHANDLED_EXCEPTION("dbaccess");
m_xComposer = nullptr;
}
// let our warnings container forget the reference to the (possibly disposed) old result set
m_aWarnings.setExternalWarnings( nullptr );
m_pCache.reset();
impl_resetTables_nothrow();
m_xStatement = nullptr;
m_xTypeMap = nullptr;
if ( m_aOldRow.is() )
m_aOldRow->clearRow();
impl_disposeParametersContainer_nothrow();
m_bCommandFacetsDirty = true;
}
void ORowSet::setActiveConnection( Reference< XConnection > const & _rxNewConn, bool _bFireEvent )
{ if (_rxNewConn.get() == m_xActiveConnection.get()) // nothing to do return;
// remove the event listener for the old connection
Reference< XComponent > xComponent(m_xActiveConnection, UNO_QUERY); if (xComponent.is())
xComponent->removeEventListener(query_aggregation<XEventListener>(this));
// if we owned the connection, remember it for later disposing if(m_bOwnConnection)
m_xOldConnection = m_xActiveConnection;
// for firing the PropertyChangeEvent
sal_Int32 nHandle = PROPERTY_ID_ACTIVE_CONNECTION;
Any aOldConnection; aOldConnection <<= m_xActiveConnection;
Any aNewConnection; aNewConnection <<= _rxNewConn;
// set the new connection
m_xActiveConnection = _rxNewConn; if (m_xActiveConnection.is())
m_aActiveConnection <<= m_xActiveConnection; else
m_aActiveConnection.clear();
// fire the event if (_bFireEvent)
fire(&nHandle, &aNewConnection, &aOldConnection, 1, false);
// register as event listener for the new connection
xComponent.set(m_xActiveConnection,UNO_QUERY); if (xComponent.is())
xComponent->addEventListener(query_aggregation<XEventListener>(this));
}
// css::XEventListener void SAL_CALL ORowSet::disposing( const css::lang::EventObject& Source )
{ // close rowset because the connection is going to be deleted (someone told me :-)
Reference<XConnection> xCon(Source.Source,UNO_QUERY); if(m_xActiveConnection == xCon)
{
close();
{
MutexGuard aGuard( m_aMutex );
Reference< XConnection > xXConnection;
setActiveConnection( xXConnection );
}
}
}
// XCloseable void SAL_CALL ORowSet::close( )
{
{
MutexGuard aGuard( m_aMutex );
::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed);
} // additional things to set
freeResources( true );
}
if ( m_pColumns )
{
Reference<XPropertySet> xColumn(m_pColumns->getByIndex(columnIndex-1),UNO_QUERY);
sal_Int32 nColType = 0;
xColumn->getPropertyValue(PROPERTY_TYPE) >>= nColType; switch( nColType )
{ case DataType::DATE: case DataType::TIME: case DataType::TIMESTAMP:
{ double nValue = 0; if ( x >>= nValue )
{ if ( DataType::TIMESTAMP == nColType )
aNewValue <<= dbtools::DBTypeConversion::toDateTime( nValue ); elseif ( DataType::DATE == nColType )
aNewValue <<= dbtools::DBTypeConversion::toDate( nValue ); else
aNewValue <<= dbtools::DBTypeConversion::toTime( nValue );
} break;
}
}
}
if (!::dbtools::implUpdateObject(this, columnIndex, aNewValue))
{ // there is no other updateXXX call which can handle the value in x
ORowSetValueVector::Vector& rRow = **m_aCurrentRow;
ORowSetNotifier aNotify(this, std::vector(rRow));
m_pCache->updateObject(columnIndex,aNewValue,rRow,aNotify.getChangedColumns());
m_bModified = m_bModified || !aNotify.getChangedColumns().empty();
aNotify.firePropertyChange();
}
}
::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); // insertRow is not allowed when // standing not on the insert row nor // when the row isn't modified // or the concurrency is read only
::osl::ResettableMutexGuard aGuard( *m_pMutex );
// this call position the cache indirect
Any aBookmarkToDelete( m_aBookmark );
positionCache( CursorMoveDirection::Current );
sal_Int32 nDeletePosition = m_pCache->getRow();
::osl::MutexGuard aGuard( *m_pMutex ); if ( m_bBeforeFirst || m_bAfterLast || rowDeleted() ) return; // nothing to do so return
checkCache(); // cancelRowUpdates is not allowed when: // - standing on the insert row // - the concurrency is read only // - the current row is deleted if ( m_bNew || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY )
throwFunctionSequenceException(*this);
positionCache( CursorMoveDirection::Current );
ORowSetRow aOldValues; if ( !m_bModified && _bNotifyModified && !m_aCurrentRow.isNull() )
aOldValues = new ORowSetValueVector( *(*m_aCurrentRow) );
if ( !notifyAllListenersCursorBeforeMove( aGuard ) ) return;
// remember old value for fire
ORowSetRow aOldValues; if ( rowDeleted() )
{
positionCache( CursorMoveDirection::Forward );
m_pCache->next();
setCurrentRow( true, false, aOldValues, aGuard);
} else
positionCache( CursorMoveDirection::Current );
// check before because the resultset could be empty if ( !m_bBeforeFirst
&& !m_bAfterLast
&& m_pCache->m_aMatrixIter != m_pCache->getEnd()
&& m_pCache->m_aMatrixIter->is()
)
aOldValues = new ORowSetValueVector( *(*(m_pCache->m_aMatrixIter)) );
if ( !m_pCache->m_bNew && !m_bModified ) // nothing to do if we're not on the insertion row, and not modified otherwise return;
if ( rowDeleted() ) // this would perhaps even justify a RuntimeException... // if the current row is deleted, then no write access to this row should be possible. So, // m_bModified should be true. Also, as soon as somebody calls moveToInsertRow, // our current row should not be deleted anymore. So, we should not have survived the above // check "if ( !m_pCache->m_bNew && !m_bModified )"
::dbtools::throwSQLException( DBA_RES( RID_STR_ROW_ALREADY_DELETED ), StandardSQLState::FUNCTION_SEQUENCE_ERROR, *this );
if ( !notifyAllListenersCursorBeforeMove( aGuard ) ) return;
// tell everybody that we will change the result set
approveExecution();
ResettableMutexGuard aGuard( m_aMutex );
try
{
freeResources( m_bCommandFacetsDirty );
// calc the connection to be used if (m_xActiveConnection.is() && m_bRebuildConnOnExecute)
{ // there was a setProperty(ActiveConnection), but a setProperty(DataSource) _after_ that, too
Reference< XConnection > xXConnection;
setActiveConnection( xXConnection );
}
calcConnection( _rxHandler );
m_bRebuildConnOnExecute = false;
::dbtools::askForParameters( xComposer, this, m_xActiveConnection, _rxHandler,m_aParametersSet );
} // ensure that only the allowed exceptions leave this block catch(SQLException&)
{ throw;
} catch(RuntimeException&)
{ throw;
} catch(Exception const &)
{
TOOLS_WARN_EXCEPTION("dbaccess", "ORowSet::executeWithCompletion: caught an unexpected exception type while filling in the parameters");
}
// we're done with the parameters, now for the real execution
// do the real execute
execute_NoApprove_NoNewConn(aGuard);
}
if ( m_bCommandFacetsDirty ) // need to rebuild the parameters, since some property which contributes to the // complete command, and thus the parameters, changed
impl_disposeParametersContainer_nothrow();
// calc the connection to be used if (m_xActiveConnection.is() && m_bRebuildConnOnExecute) { // there was a setProperty(ActiveConnection), but a setProperty(DataSource) _after_ that, too
Reference< XConnection> xXConnection;
setActiveConnection( xXConnection );
}
// there *might* be a data source setting which tells use to be more defensive with those settings // #i15113# bool bRespectDriverRST = false;
Any aSetting; if (getDataSourceSetting(::dbaccess::getDataSource(m_xActiveConnection), u"RespectDriverResultSetType"_ustr, aSetting))
{
OSL_VERIFY( aSetting >>= bRespectDriverRST );
}
if ( bRespectDriverRST )
{ // try type/concurrency settings with decreasing usefulness, and rely on what the connection claims // to support
Reference< XDatabaseMetaData > xMeta( m_xActiveConnection->getMetaData() );
sal_Int32 nCharacteristics[5][2] =
{ { ResultSetType::SCROLL_SENSITIVE, ResultSetConcurrency::UPDATABLE },
{ ResultSetType::SCROLL_INSENSITIVE, ResultSetConcurrency::UPDATABLE },
{ ResultSetType::SCROLL_SENSITIVE, ResultSetConcurrency::READ_ONLY },
{ ResultSetType::SCROLL_INSENSITIVE, ResultSetConcurrency::READ_ONLY },
{ ResultSetType::FORWARD_ONLY, ResultSetConcurrency::READ_ONLY }
};
sal_Int32 i=0; if ( m_xActiveConnection->getMetaData()->isReadOnly() )
i = 2; // if the database is read-only we only should use read-only concurrency
// don't try type/concurrency pairs which are more featured than what our caller requested if ( nResultSetType > _nDesiredResultSetType ) continue; if ( nResultSetConcurrency > _nDesiredResultSetConcurrency ) continue;
Reference< XPropertySet > xStatementProps( m_xStatement, UNO_QUERY_THROW ); // set the result set type and concurrency try
{
xStatementProps->setPropertyValue( PROPERTY_USEBOOKMARKS, Any( true ) );
xStatementProps->setPropertyValue( PROPERTY_MAXROWS, Any( m_nMaxRows ) );
setStatementResultSetType( xStatementProps, m_nResultSetType, m_nResultSetConcurrency );
} catch ( const Exception& )
{ // this exception doesn't matter here because when we catch an exception // then the driver doesn't support this feature
}
} catch (SQLException& rException)
{
css::sdbc::SQLException* pLastExceptionInChain = SQLExceptionInfo::getLastException(&rException);
assert(pLastExceptionInChain && "will at least be &rException");
// append information about what we were actually going to execute
OUString sInfo(m_sErrorString.replaceFirst("$command$", sCommandToExecute));
pLastExceptionInChain->NextException = SQLExceptionInfo::createException(SQLExceptionInfo::TYPE::SQLContext, sInfo, OUString(), 0);
// the template column could not provide *any* setting. Okay, probably it's a parser column, which // does not offer those. However, perhaps the template column refers to a table column, which we // can use as new template column try
{
Reference< XPropertySetInfo > xInfo( _rxTemplateColumn->getPropertySetInfo(), UNO_SET_THROW ); if ( !xInfo->hasPropertyByName( PROPERTY_TABLENAME ) ) // no chance return;
void ORowSet::execute_NoApprove_NoNewConn(ResettableMutexGuard& _rClearForNotification)
{ // now we can dispose our old connection
::comphelper::disposeComponent(m_xOldConnection);
m_xOldConnection = nullptr;
// do we need a new statement if ( m_bCommandFacetsDirty )
{
m_xStatement = nullptr;
m_xComposer = nullptr;
// let our warnings container forget the reference to the (possibly disposed) old result set
m_aWarnings.setExternalWarnings( nullptr ); // clear all current warnings
m_aWarnings.clearWarnings(); // let the warnings container know about the new "external warnings"
m_aWarnings.setExternalWarnings( Reference< XWarningsSupplier >( xResultSet, UNO_QUERY ) );
// get the locale
Locale aLocale = SvtSysLocale().GetLanguageTag().getLocale();
// get the numberformatTypes
OSL_ENSURE(m_xActiveConnection.is(),"No ActiveConnection");
Reference< XNumberFormatsSupplier> xNumberFormat = ::dbtools::getNumberFormats(m_xActiveConnection); if ( xNumberFormat.is() )
m_xNumberFormatTypes.set(xNumberFormat->getNumberFormats(),UNO_QUERY);
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.31 Sekunden
(vorverarbeitet)
¤
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.