1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_dbaccess.hxx" 26 #include <iterator> 27 28 #include "connection.hxx" 29 #include "dbastrings.hrc" 30 #include "datasource.hxx" 31 #include "core_resource.hrc" 32 #include "core_resource.hxx" 33 #include "statement.hxx" 34 #include "preparedstatement.hxx" 35 #include "callablestatement.hxx" 36 #include "ContainerMediator.hxx" 37 #include "SingleSelectQueryComposer.hxx" 38 #include "querycomposer.hxx" 39 #include "sdbcoretools.hxx" 40 41 /** === begin UNO includes === **/ 42 #include <com/sun/star/sdb/CommandType.hpp> 43 #include <com/sun/star/sdbc/XDriverAccess.hpp> 44 #include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp> 45 #include <com/sun/star/reflection/XProxyFactory.hpp> 46 #include <com/sun/star/beans/NamedValue.hpp> 47 /** === end UNO includes === **/ 48 #include <connectivity/dbtools.hxx> 49 #include <connectivity/dbmetadata.hxx> 50 #include <connectivity/dbexception.hxx> 51 #include <tools/debug.hxx> 52 #include <tools/diagnose_ex.h> 53 #include <comphelper/extract.hxx> 54 #include <comphelper/uno3.hxx> 55 #include <comphelper/sequence.hxx> 56 #include <cppuhelper/typeprovider.hxx> 57 #include <rtl/logfile.hxx> 58 #include "SharedConnection.hxx" 59 60 using namespace ::com::sun::star::uno; 61 using namespace ::com::sun::star::lang; 62 using namespace ::com::sun::star::util; 63 using namespace ::com::sun::star::sdb; 64 using namespace ::com::sun::star::sdb::application; 65 using namespace ::com::sun::star::sdbc; 66 using namespace ::com::sun::star::sdbcx; 67 using namespace ::com::sun::star::beans; 68 using namespace ::com::sun::star::reflection; 69 using namespace ::com::sun::star::container; 70 using namespace ::com::sun::star::graphic; 71 using namespace ::osl; 72 using namespace ::comphelper; 73 using namespace ::cppu; 74 using namespace ::dbtools; 75 76 using ::com::sun::star::sdb::tools::XTableName; 77 using ::com::sun::star::sdb::tools::XObjectNames; 78 using ::com::sun::star::sdb::tools::XDataSourceMetaData; 79 80 //........................................................................ 81 namespace dbaccess 82 { 83 //........................................................................ 84 #ifdef IMPLEMENT_GET_IMPLEMENTATION_ID 85 IMPLEMENT_GET_IMPLEMENTATION_ID( OSharedConnection ); 86 #endif 87 88 //========================================================================== 89 // XServiceInfo 90 //------------------------------------------------------------------------------ 91 rtl::OUString OConnection::getImplementationName( ) 92 { 93 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getImplementationName" ); 94 return rtl::OUString::createFromAscii("com.sun.star.comp.dbaccess.Connection"); 95 } 96 //------------------------------------------------------------------------------ 97 sal_Bool OConnection::supportsService( const ::rtl::OUString& _rServiceName ) 98 { 99 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::supportsService" ); 100 return findValue(getSupportedServiceNames(), _rServiceName, sal_True).getLength() != 0; 101 } 102 103 //------------------------------------------------------------------------------ 104 Sequence< ::rtl::OUString > OConnection::getSupportedServiceNames( ) 105 { 106 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getSupportedServiceNames" ); 107 Sequence< ::rtl::OUString > aSupported = OConnectionWrapper::getSupportedServiceNames(); 108 109 if ( 0 == findValue( aSupported, SERVICE_SDB_CONNECTION, sal_True ).getLength() ) 110 { 111 sal_Int32 nLen = aSupported.getLength(); 112 aSupported.realloc( nLen + 1 ); 113 aSupported[ nLen ] = SERVICE_SDB_CONNECTION; 114 } 115 116 return aSupported; 117 } 118 119 // XCloseable 120 //------------------------------------------------------------------------------ 121 void OConnection::close(void) 122 { 123 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::close" ); 124 // being closed is the same as being disposed 125 dispose(); 126 } 127 128 //------------------------------------------------------------------------------ 129 sal_Bool OConnection::isClosed(void) 130 { 131 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::isClosed" ); 132 MutexGuard aGuard(m_aMutex); 133 return !m_xMasterConnection.is(); 134 } 135 136 // XConnection 137 //------------------------------------------------------------------------------ 138 Reference< XStatement > OConnection::createStatement(void) 139 { 140 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::createStatement" ); 141 MutexGuard aGuard(m_aMutex); 142 checkDisposed(); 143 144 Reference< XStatement > xStatement; 145 Reference< XStatement > xMasterStatement = m_xMasterConnection->createStatement(); 146 if ( xMasterStatement.is() ) 147 { 148 xStatement = new OStatement(this, xMasterStatement); 149 m_aStatements.push_back(WeakReferenceHelper(xStatement)); 150 } 151 return xStatement; 152 } 153 //------------------------------------------------------------------------------ 154 Reference< XPreparedStatement > OConnection::prepareStatement(const rtl::OUString& sql) 155 { 156 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::prepareStatement" ); 157 MutexGuard aGuard(m_aMutex); 158 checkDisposed(); 159 160 // TODO convert the SQL to SQL the driver understands 161 Reference< XPreparedStatement > xStatement; 162 Reference< XPreparedStatement > xMasterStatement = m_xMasterConnection->prepareStatement(sql); 163 if ( xMasterStatement.is() ) 164 { 165 xStatement = new OPreparedStatement(this, xMasterStatement); 166 m_aStatements.push_back(WeakReferenceHelper(xStatement)); 167 } 168 return xStatement; 169 } 170 171 //------------------------------------------------------------------------------ 172 Reference< XPreparedStatement > OConnection::prepareCall(const rtl::OUString& sql) 173 { 174 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::prepareCall" ); 175 MutexGuard aGuard(m_aMutex); 176 checkDisposed(); 177 178 Reference< XPreparedStatement > xStatement; 179 Reference< XPreparedStatement > xMasterStatement = m_xMasterConnection->prepareCall(sql); 180 if ( xMasterStatement.is() ) 181 { 182 xStatement = new OCallableStatement(this, xMasterStatement); 183 m_aStatements.push_back(WeakReferenceHelper(xStatement)); 184 } 185 return xStatement; 186 } 187 188 //------------------------------------------------------------------------------ 189 rtl::OUString OConnection::nativeSQL(const rtl::OUString& sql) 190 { 191 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::nativeSQL" ); 192 MutexGuard aGuard(m_aMutex); 193 checkDisposed(); 194 return m_xMasterConnection->nativeSQL(sql); 195 } 196 197 //------------------------------------------------------------------------------ 198 void OConnection::setAutoCommit(sal_Bool autoCommit) 199 { 200 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::setAutoCommit" ); 201 MutexGuard aGuard(m_aMutex); 202 checkDisposed(); 203 m_xMasterConnection->setAutoCommit(autoCommit); 204 } 205 206 //------------------------------------------------------------------------------ 207 sal_Bool OConnection::getAutoCommit(void) 208 { 209 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getAutoCommit" ); 210 MutexGuard aGuard(m_aMutex); 211 checkDisposed(); 212 return m_xMasterConnection->getAutoCommit(); 213 } 214 215 //------------------------------------------------------------------------------ 216 void OConnection::commit(void) 217 { 218 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::commit" ); 219 MutexGuard aGuard(m_aMutex); 220 checkDisposed(); 221 m_xMasterConnection->commit(); 222 } 223 224 //------------------------------------------------------------------------------ 225 void OConnection::rollback(void) 226 { 227 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::rollback" ); 228 MutexGuard aGuard(m_aMutex); 229 checkDisposed(); 230 m_xMasterConnection->rollback(); 231 } 232 233 //------------------------------------------------------------------------------ 234 Reference< XDatabaseMetaData > OConnection::getMetaData(void) 235 { 236 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getMetaData" ); 237 MutexGuard aGuard(m_aMutex); 238 checkDisposed(); 239 return m_xMasterConnection->getMetaData(); 240 } 241 242 //------------------------------------------------------------------------------ 243 void OConnection::setReadOnly(sal_Bool readOnly) 244 { 245 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::setReadOnly" ); 246 MutexGuard aGuard(m_aMutex); 247 checkDisposed(); 248 m_xMasterConnection->setReadOnly(readOnly); 249 } 250 251 //------------------------------------------------------------------------------ 252 sal_Bool OConnection::isReadOnly(void) 253 { 254 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::isReadOnly" ); 255 MutexGuard aGuard(m_aMutex); 256 checkDisposed(); 257 return m_xMasterConnection->isReadOnly(); 258 } 259 260 //------------------------------------------------------------------------------ 261 void OConnection::setCatalog(const rtl::OUString& catalog) 262 { 263 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::setCatalog" ); 264 MutexGuard aGuard(m_aMutex); 265 checkDisposed(); 266 m_xMasterConnection->setCatalog(catalog); 267 } 268 269 //------------------------------------------------------------------------------ 270 rtl::OUString OConnection::getCatalog(void) 271 { 272 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getCatalog" ); 273 MutexGuard aGuard(m_aMutex); 274 checkDisposed(); 275 return m_xMasterConnection->getCatalog(); 276 } 277 278 //------------------------------------------------------------------------------ 279 void OConnection::setTransactionIsolation(sal_Int32 level) 280 { 281 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::setTransactionIsolation" ); 282 MutexGuard aGuard(m_aMutex); 283 checkDisposed(); 284 m_xMasterConnection->setTransactionIsolation(level); 285 } 286 287 //------------------------------------------------------------------------------ 288 sal_Int32 OConnection::getTransactionIsolation(void) 289 { 290 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getTransactionIsolation" ); 291 MutexGuard aGuard(m_aMutex); 292 checkDisposed(); 293 return m_xMasterConnection->getTransactionIsolation(); 294 } 295 296 //------------------------------------------------------------------------------ 297 Reference< XNameAccess > OConnection::getTypeMap(void) 298 { 299 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getTypeMap" ); 300 MutexGuard aGuard(m_aMutex); 301 checkDisposed(); 302 return m_xMasterConnection->getTypeMap(); 303 } 304 305 //------------------------------------------------------------------------------ 306 void OConnection::setTypeMap(const Reference< XNameAccess > & typeMap) 307 { 308 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::setTypeMap" ); 309 MutexGuard aGuard(m_aMutex); 310 checkDisposed(); 311 m_xMasterConnection->setTypeMap(typeMap); 312 } 313 //========================================================================== 314 //= OConnection 315 //========================================================================== 316 DBG_NAME(OConnection) 317 //-------------------------------------------------------------------------- 318 OConnection::OConnection(ODatabaseSource& _rDB 319 , Reference< XConnection >& _rxMaster 320 , const Reference< XMultiServiceFactory >& _rxORB) 321 :OSubComponent(m_aMutex, static_cast< OWeakObject* >(&_rDB)) 322 // as the queries reroute their refcounting to us, this m_aMutex is okey. If the queries 323 // container would do it's own refcounting, it would have to acquire m_pMutex 324 // same for tables 325 ,m_aTableFilter(_rDB.m_pImpl->m_aTableFilter) 326 ,m_aTableTypeFilter(_rDB.m_pImpl->m_aTableTypeFilter) 327 ,m_aContext( _rxORB ) 328 ,m_xMasterConnection(_rxMaster) 329 ,m_pTables(NULL) 330 ,m_pViews(NULL) 331 ,m_aWarnings( Reference< XWarningsSupplier >( _rxMaster, UNO_QUERY ) ) 332 ,m_nInAppend(0) 333 ,m_bSupportsViews(sal_False) 334 ,m_bSupportsUsers(sal_False) 335 ,m_bSupportsGroups(sal_False) 336 { 337 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::OConnection" ); 338 DBG_CTOR(OConnection,NULL); 339 osl_incrementInterlockedCount(&m_refCount); 340 341 try 342 { 343 Reference< XProxyFactory > xProxyFactory( 344 _rxORB->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.ProxyFactory"))),UNO_QUERY); 345 Reference<XAggregation> xAgg = xProxyFactory->createProxy(_rxMaster.get()); 346 setDelegation(xAgg,m_refCount); 347 DBG_ASSERT(m_xConnection.is(), "OConnection::OConnection : invalid master connection !"); 348 } 349 catch(const Exception&) 350 { 351 DBG_UNHANDLED_EXCEPTION(); 352 } 353 354 m_xTableUIProvider = m_xTableUIProvider.query( m_xMasterConnection ); 355 356 try 357 { 358 m_xQueries = new OQueryContainer(Reference< XNameContainer >(_rDB.getQueryDefinitions( ),UNO_QUERY), this,_rxORB, &m_aWarnings); 359 360 sal_Bool bCase = sal_True; 361 Reference<XDatabaseMetaData> xMeta; 362 try 363 { 364 xMeta = getMetaData(); 365 bCase = xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(); 366 } 367 catch(SQLException&) 368 { 369 } 370 Reference< XNameContainer > xTableDefinitions(_rDB.getTables(),UNO_QUERY); 371 m_pTables = new OTableContainer( *this, m_aMutex, this, bCase, xTableDefinitions, this, &m_aWarnings,m_nInAppend ); 372 373 // check if we supports types 374 if ( xMeta.is() ) 375 { 376 Reference<XResultSet> xRes = xMeta->getTableTypes(); 377 if(xRes.is()) 378 { 379 ::rtl::OUString sView(RTL_CONSTASCII_USTRINGPARAM("VIEW")); 380 Reference<XRow> xRow(xRes,UNO_QUERY); 381 while(xRes->next()) 382 { 383 ::rtl::OUString sValue = xRow->getString(1); 384 if( !xRow->wasNull() && sValue == sView) 385 { 386 m_bSupportsViews = sal_True; 387 break; 388 } 389 } 390 } 391 // some dbs don't support this type so we should ask if a XViewsSupplier is supported 392 if(!m_bSupportsViews) 393 { 394 Reference< XViewsSupplier > xMaster(getMasterTables(),UNO_QUERY); 395 396 if (xMaster.is() && xMaster->getViews().is()) 397 m_bSupportsViews = sal_True; 398 } 399 if(m_bSupportsViews) 400 { 401 m_pViews = new OViewContainer(*this, m_aMutex, this, bCase,this,&m_aWarnings,m_nInAppend); 402 m_pViews->addContainerListener(m_pTables); 403 m_pTables->addContainerListener(m_pViews); 404 } 405 m_bSupportsUsers = Reference< XUsersSupplier> (getMasterTables(),UNO_QUERY).is(); 406 m_bSupportsGroups = Reference< XGroupsSupplier> (getMasterTables(),UNO_QUERY).is(); 407 408 impl_checkTableQueryNames_nothrow(); 409 } 410 } 411 catch(const Exception& ) 412 { 413 DBG_UNHANDLED_EXCEPTION(); 414 } 415 osl_decrementInterlockedCount( &m_refCount ); 416 } 417 418 //-------------------------------------------------------------------------- 419 OConnection::~OConnection() 420 { 421 delete m_pTables; 422 delete m_pViews; 423 DBG_DTOR(OConnection,NULL); 424 } 425 426 427 // XWarningsSupplier 428 //-------------------------------------------------------------------------- 429 Any SAL_CALL OConnection::getWarnings() 430 { 431 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getWarnings" ); 432 MutexGuard aGuard(m_aMutex); 433 checkDisposed(); 434 return m_aWarnings.getWarnings(); 435 } 436 437 //-------------------------------------------------------------------------- 438 void SAL_CALL OConnection::clearWarnings( ) 439 { 440 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::clearWarnings" ); 441 MutexGuard aGuard(m_aMutex); 442 checkDisposed(); 443 m_aWarnings.clearWarnings(); 444 } 445 446 //-------------------------------------------------------------------------- 447 namespace 448 { 449 struct CompareTypeByName : public ::std::binary_function< Type, Type, bool > 450 { 451 bool operator() ( const Type& _rLHS, const Type& _rRHS ) const 452 { 453 return _rLHS.getTypeName() < _rRHS.getTypeName(); 454 } 455 }; 456 typedef ::std::set< Type, CompareTypeByName > TypeBag; 457 458 void lcl_copyTypes( TypeBag& _out_rTypes, const Sequence< Type >& _rTypes ) 459 { 460 ::std::copy( _rTypes.getConstArray(), _rTypes.getConstArray() + _rTypes.getLength(), 461 ::std::insert_iterator< TypeBag >( _out_rTypes, _out_rTypes.begin() ) ); 462 } 463 } 464 // com::sun::star::lang::XTypeProvider 465 //-------------------------------------------------------------------------- 466 Sequence< Type > OConnection::getTypes() 467 { 468 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getTypes" ); 469 TypeBag aNormalizedTypes; 470 471 lcl_copyTypes( aNormalizedTypes, OSubComponent::getTypes() ); 472 lcl_copyTypes( aNormalizedTypes, OConnection_Base::getTypes() ); 473 lcl_copyTypes( aNormalizedTypes, ::connectivity::OConnectionWrapper::getTypes() ); 474 475 if ( !m_bSupportsViews ) 476 aNormalizedTypes.erase( XViewsSupplier::static_type() ); 477 if ( !m_bSupportsUsers ) 478 aNormalizedTypes.erase( XUsersSupplier::static_type() ); 479 if ( !m_bSupportsGroups ) 480 aNormalizedTypes.erase( XGroupsSupplier::static_type() ); 481 482 Sequence< Type > aSupportedTypes( aNormalizedTypes.size() ); 483 ::std::copy( aNormalizedTypes.begin(), aNormalizedTypes.end(), aSupportedTypes.getArray() ); 484 return aSupportedTypes; 485 } 486 487 //-------------------------------------------------------------------------- 488 Sequence< sal_Int8 > OConnection::getImplementationId() 489 { 490 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getImplementationId" ); 491 return getUnoTunnelImplementationId(); 492 } 493 494 // com::sun::star::uno::XInterface 495 //-------------------------------------------------------------------------- 496 Any OConnection::queryInterface( const Type & rType ) 497 { 498 if ( !m_bSupportsViews && rType.equals( XViewsSupplier::static_type() ) ) 499 return Any(); 500 else if ( !m_bSupportsUsers && rType.equals( XUsersSupplier::static_type() ) ) 501 return Any(); 502 else if ( !m_bSupportsGroups && rType.equals( XGroupsSupplier::static_type() ) ) 503 return Any(); 504 Any aReturn = OSubComponent::queryInterface( rType ); 505 if (!aReturn.hasValue()) 506 { 507 aReturn = OConnection_Base::queryInterface( rType ); 508 if (!aReturn.hasValue()) 509 aReturn = OConnectionWrapper::queryInterface( rType ); 510 } 511 return aReturn; 512 } 513 514 //-------------------------------------------------------------------------- 515 void OConnection::acquire() throw () 516 { 517 // include this one when you want to see who calls it (call graph) 518 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::acquire" ); 519 OSubComponent::acquire(); 520 } 521 522 //-------------------------------------------------------------------------- 523 void OConnection::release() throw () 524 { 525 // include this one when you want to see who calls it (call graph) 526 //RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::release" ); 527 OSubComponent::release(); 528 } 529 530 // OSubComponent 531 //------------------------------------------------------------------------------ 532 void OConnection::disposing() 533 { 534 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::disposing" ); 535 MutexGuard aGuard(m_aMutex); 536 537 OSubComponent::disposing(); 538 OConnectionWrapper::disposing(); 539 540 OWeakRefArrayIterator aEnd = m_aStatements.end(); 541 for (OWeakRefArrayIterator i = m_aStatements.begin(); aEnd != i; ++i) 542 { 543 Reference<XComponent> xComp(i->get(),UNO_QUERY); 544 ::comphelper::disposeComponent(xComp); 545 } 546 m_aStatements.clear(); 547 m_xMasterTables = NULL; 548 549 if(m_pTables) 550 m_pTables->dispose(); 551 if(m_pViews) 552 m_pViews->dispose(); 553 554 ::comphelper::disposeComponent(m_xQueries); 555 556 OWeakRefArrayIterator aComposerEnd = m_aComposers.end(); 557 for (OWeakRefArrayIterator j = m_aComposers.begin(); aComposerEnd != j; ++j) 558 { 559 Reference<XComponent> xComp(j->get(),UNO_QUERY); 560 ::comphelper::disposeComponent(xComp); 561 } 562 563 m_aComposers.clear(); 564 565 try 566 { 567 if (m_xMasterConnection.is()) 568 m_xMasterConnection->close(); 569 } 570 catch(Exception) 571 { 572 } 573 m_xMasterConnection = NULL; 574 } 575 576 // XChild 577 //------------------------------------------------------------------------------ 578 Reference< XInterface > OConnection::getParent(void) 579 { 580 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getParent" ); 581 MutexGuard aGuard(m_aMutex); 582 checkDisposed(); 583 return m_xParent; 584 } 585 586 //------------------------------------------------------------------------------ 587 void OConnection::setParent(const Reference< XInterface > & /*Parent*/) 588 { 589 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::setParent" ); 590 throw NoSupportException(); 591 } 592 593 // XSQLQueryComposerFactory 594 //------------------------------------------------------------------------------ 595 Reference< XSQLQueryComposer > OConnection::createQueryComposer(void) 596 { 597 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::createQueryComposer" ); 598 MutexGuard aGuard(m_aMutex); 599 checkDisposed(); 600 601 // Reference< XNumberFormatsSupplier > xSupplier = pParent->getNumberFormatsSupplier(); 602 Reference< XSQLQueryComposer > xComposer( new OQueryComposer( this ) ); 603 m_aComposers.push_back(WeakReferenceHelper(xComposer)); 604 return xComposer; 605 } 606 // ----------------------------------------------------------------------------- 607 void OConnection::impl_fillTableFilter() 608 { 609 Reference<XPropertySet> xProp(getParent(),UNO_QUERY); 610 if ( xProp.is() ) 611 { 612 xProp->getPropertyValue(PROPERTY_TABLEFILTER) >>= m_aTableFilter; 613 xProp->getPropertyValue(PROPERTY_TABLETYPEFILTER) >>= m_aTableTypeFilter; 614 } 615 } 616 617 // ----------------------------------------------------------------------------- 618 void OConnection::refresh(const Reference< XNameAccess >& _rToBeRefreshed) 619 { 620 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::refresh" ); 621 if ( _rToBeRefreshed == Reference< XNameAccess >(m_pTables) ) 622 { 623 if (m_pTables && !m_pTables->isInitialized()) 624 { 625 impl_fillTableFilter(); 626 // check if our "master connection" can supply tables 627 getMasterTables(); 628 629 if (m_xMasterTables.is() && m_xMasterTables->getTables().is()) 630 { // yes -> wrap them 631 m_pTables->construct(m_xMasterTables->getTables(),m_aTableFilter, m_aTableTypeFilter); 632 } 633 else 634 { // no -> use an own container 635 m_pTables->construct(m_aTableFilter, m_aTableTypeFilter); 636 } 637 } 638 } 639 else if ( _rToBeRefreshed == Reference< XNameAccess >(m_pViews) ) 640 { 641 if (m_pViews && !m_pViews->isInitialized()) 642 { 643 impl_fillTableFilter(); 644 // check if our "master connection" can supply tables 645 Reference< XViewsSupplier > xMaster(getMasterTables(),UNO_QUERY); 646 647 if (xMaster.is() && xMaster->getViews().is()) 648 m_pViews->construct(xMaster->getViews(),m_aTableFilter, m_aTableTypeFilter); 649 else 650 m_pViews->construct(m_aTableFilter, m_aTableTypeFilter); 651 } 652 } 653 } 654 // ----------------------------------------------------------------------------- 655 656 // XTablesSupplier 657 //------------------------------------------------------------------------------ 658 Reference< XNameAccess > OConnection::getTables() 659 { 660 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getTables" ); 661 MutexGuard aGuard(m_aMutex); 662 checkDisposed(); 663 664 refresh(m_pTables); 665 666 return m_pTables; 667 } 668 // ----------------------------------------------------------------------------- 669 Reference< XNameAccess > SAL_CALL OConnection::getViews( ) 670 { 671 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getViews" ); 672 MutexGuard aGuard(m_aMutex); 673 checkDisposed(); 674 675 refresh(m_pViews); 676 677 return m_pViews; 678 } 679 // XQueriesSupplier 680 //------------------------------------------------------------------------------ 681 Reference< XNameAccess > OConnection::getQueries(void) 682 { 683 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getQueries" ); 684 MutexGuard aGuard(m_aMutex); 685 checkDisposed(); 686 687 return m_xQueries; 688 } 689 690 // ::com::sun::star::sdb::XCommandPreparation 691 //------------------------------------------------------------------------------ 692 Reference< XPreparedStatement > SAL_CALL OConnection::prepareCommand( const ::rtl::OUString& command, sal_Int32 commandType ) 693 { 694 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::prepareCommand" ); 695 MutexGuard aGuard(m_aMutex); 696 checkDisposed(); 697 698 rtl::OUString aStatement; 699 switch (commandType) 700 { 701 case CommandType::TABLE: 702 { 703 aStatement = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SELECT * FROM ")); 704 705 ::rtl::OUString sCatalog, sSchema, sTable; 706 ::dbtools::qualifiedNameComponents( getMetaData(), command, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation ); 707 aStatement += ::dbtools::composeTableNameForSelect( this, sCatalog, sSchema, sTable ); 708 } 709 break; 710 case CommandType::QUERY: 711 if ( m_xQueries->hasByName(command) ) 712 { 713 Reference< XPropertySet > xQuery(m_xQueries->getByName(command),UNO_QUERY); 714 xQuery->getPropertyValue(PROPERTY_COMMAND) >>= aStatement; 715 } 716 break; 717 default: 718 aStatement = command; 719 } 720 // TODO EscapeProcessing 721 return prepareStatement(aStatement); 722 } 723 // ----------------------------------------------------------------------------- 724 Reference< XInterface > SAL_CALL OConnection::createInstance( const ::rtl::OUString& _sServiceSpecifier ) 725 { 726 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::createInstance" ); 727 Reference< XServiceInfo > xRet; 728 if ( ( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER == _sServiceSpecifier ) 729 || ( _sServiceSpecifier.equalsAscii( "com.sun.star.sdb.SingleSelectQueryAnalyzer" ) ) 730 ) 731 { 732 xRet = new OSingleSelectQueryComposer( getTables(),this, m_aContext ); 733 m_aComposers.push_back(WeakReferenceHelper(xRet)); 734 } 735 else 736 { 737 if ( _sServiceSpecifier.getLength() ) 738 { 739 TSupportServices::iterator aFind = m_aSupportServices.find(_sServiceSpecifier); 740 if ( aFind == m_aSupportServices.end() ) 741 { 742 Sequence<Any> aArgs(1); 743 Reference<XConnection> xMy(this); 744 aArgs[0] <<= NamedValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ActiveConnection")),makeAny(xMy)); 745 aFind = m_aSupportServices.insert(TSupportServices::value_type(_sServiceSpecifier,m_aContext.createComponentWithArguments(_sServiceSpecifier,aArgs))).first; 746 } 747 return aFind->second; 748 } 749 } 750 return Reference< XInterface >(xRet,UNO_QUERY); 751 } 752 // ----------------------------------------------------------------------------- 753 Reference< XInterface > SAL_CALL OConnection::createInstanceWithArguments( const ::rtl::OUString& _sServiceSpecifier, const Sequence< Any >& /*Arguments*/ ) 754 { 755 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::createInstanceWithArguments" ); 756 return createInstance(_sServiceSpecifier); 757 } 758 // ----------------------------------------------------------------------------- 759 Sequence< ::rtl::OUString > SAL_CALL OConnection::getAvailableServiceNames( ) 760 { 761 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getAvailableServiceNames" ); 762 Sequence< ::rtl::OUString > aRet(1); 763 aRet[0] = SERVICE_NAME_SINGLESELECTQUERYCOMPOSER; 764 return aRet; 765 } 766 // ----------------------------------------------------------------------------- 767 Reference< XTablesSupplier > OConnection::getMasterTables() 768 { 769 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getMasterTables" ); 770 // check if out "master connection" can supply tables 771 if(!m_xMasterTables.is()) 772 { 773 try 774 { 775 Reference<XDatabaseMetaData> xMeta = getMetaData(); 776 if ( xMeta.is() ) 777 m_xMasterTables = ::dbtools::getDataDefinitionByURLAndConnection( xMeta->getURL(), m_xMasterConnection, m_aContext.getLegacyServiceFactory() ); 778 } 779 catch(SQLException&) 780 { 781 } 782 } 783 return m_xMasterTables; 784 } 785 // ----------------------------------------------------------------------------- 786 // XUsersSupplier 787 Reference< XNameAccess > SAL_CALL OConnection::getUsers( ) 788 { 789 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getUsers" ); 790 MutexGuard aGuard(m_aMutex); 791 checkDisposed(); 792 793 Reference<XUsersSupplier> xUsr(getMasterTables(),UNO_QUERY); 794 return xUsr.is() ? xUsr->getUsers() : Reference< XNameAccess >(); 795 } 796 // ----------------------------------------------------------------------------- 797 // XGroupsSupplier 798 Reference< XNameAccess > SAL_CALL OConnection::getGroups( ) 799 { 800 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getGroups" ); 801 MutexGuard aGuard(m_aMutex); 802 checkDisposed(); 803 Reference<XGroupsSupplier> xGrp(getMasterTables(),UNO_QUERY); 804 return xGrp.is() ? xGrp->getGroups() : Reference< XNameAccess >(); 805 } 806 807 // ----------------------------------------------------------------------------- 808 void OConnection::impl_loadConnectionTools_throw() 809 { 810 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::impl_loadConnectionTools_throw" ); 811 Sequence< Any > aArguments( 1 ); 812 aArguments[0] <<= NamedValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Connection" ) ), makeAny( Reference< XConnection >( this ) ) ); 813 814 if ( !m_aContext.createComponentWithArguments( "com.sun.star.sdb.tools.ConnectionTools", aArguments, m_xConnectionTools ) ) 815 throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "service not registered: com.sun.star.sdb.tools.ConnectionTools" ) ), *this ); 816 } 817 818 // ----------------------------------------------------------------------------- 819 Reference< XTableName > SAL_CALL OConnection::createTableName( ) 820 { 821 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::createTableName" ); 822 MutexGuard aGuard(m_aMutex); 823 checkDisposed(); 824 impl_loadConnectionTools_throw(); 825 826 return m_xConnectionTools->createTableName(); 827 } 828 829 // ----------------------------------------------------------------------------- 830 Reference< XObjectNames > SAL_CALL OConnection::getObjectNames( ) 831 { 832 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getObjectNames" ); 833 MutexGuard aGuard(m_aMutex); 834 checkDisposed(); 835 impl_loadConnectionTools_throw(); 836 837 return m_xConnectionTools->getObjectNames(); 838 } 839 840 // ----------------------------------------------------------------------------- 841 Reference< XDataSourceMetaData > SAL_CALL OConnection::getDataSourceMetaData( ) 842 { 843 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getDataSourceMetaData" ); 844 MutexGuard aGuard(m_aMutex); 845 checkDisposed(); 846 impl_loadConnectionTools_throw(); 847 848 return m_xConnectionTools->getDataSourceMetaData(); 849 } 850 // ----------------------------------------------------------------------------- 851 Reference< ::com::sun::star::container::XNameAccess > SAL_CALL OConnection::getFieldsByCommandDescriptor( ::sal_Int32 commandType, const ::rtl::OUString& command, ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& keepFieldsAlive ) 852 { 853 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getFieldsByCommandDescriptor" ); 854 MutexGuard aGuard(m_aMutex); 855 checkDisposed(); 856 impl_loadConnectionTools_throw(); 857 858 return m_xConnectionTools->getFieldsByCommandDescriptor(commandType,command,keepFieldsAlive); 859 } 860 //-------------------------------------------------------------------- 861 Reference< XSingleSelectQueryComposer > SAL_CALL OConnection::getComposer( ::sal_Int32 commandType, const ::rtl::OUString& command ) 862 { 863 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getComposer" ); 864 MutexGuard aGuard(m_aMutex); 865 checkDisposed(); 866 impl_loadConnectionTools_throw(); 867 868 return m_xConnectionTools->getComposer(commandType,command); 869 } 870 871 // ----------------------------------------------------------------------------- 872 void OConnection::impl_checkTableQueryNames_nothrow() 873 { 874 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::impl_checkTableQueryNames_nothrow" ); 875 DatabaseMetaData aMeta( static_cast< XConnection* >( this ) ); 876 if ( !aMeta.supportsSubqueriesInFrom() ) 877 // nothing to do 878 return; 879 880 try 881 { 882 Reference< XNameAccess > xTables( getTables() ); 883 Sequence< ::rtl::OUString > aTableNames( xTables->getElementNames() ); 884 ::std::set< ::rtl::OUString > aSortedTableNames( aTableNames.getConstArray(), aTableNames.getConstArray() + aTableNames.getLength() ); 885 886 Reference< XNameAccess > xQueries( getQueries() ); 887 Sequence< ::rtl::OUString > aQueryNames( xQueries->getElementNames() ); 888 889 for ( const ::rtl::OUString* pQueryName = aQueryNames.getConstArray(); 890 pQueryName != aQueryNames.getConstArray() + aQueryNames.getLength(); 891 ++pQueryName 892 ) 893 { 894 if ( aSortedTableNames.find( *pQueryName ) != aSortedTableNames.end() ) 895 { 896 ::rtl::OUString sConflictWarning( DBACORE_RESSTRING( RID_STR_CONFLICTING_NAMES ) ); 897 m_aWarnings.appendWarning( sConflictWarning, "01SB0", *this ); 898 } 899 } 900 } 901 catch( const Exception& ) 902 { 903 DBG_UNHANDLED_EXCEPTION(); 904 } 905 } 906 907 // ----------------------------------------------------------------------------- 908 Reference< XGraphic > SAL_CALL OConnection::getTableIcon( const ::rtl::OUString& _TableName, ::sal_Int32 _ColorMode ) 909 { 910 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getTableIcon" ); 911 Reference< XGraphic > xReturn; 912 913 // ask our aggregate 914 if ( m_xTableUIProvider.is() ) 915 xReturn = m_xTableUIProvider->getTableIcon( _TableName, _ColorMode ); 916 917 // ask ourself 918 // well, we don't have own functionality here ... 919 // In the future, we might decide to delegate the complete handling to this interface. 920 // In this case, we would need to load the icon here. 921 922 return xReturn; 923 } 924 925 // ----------------------------------------------------------------------------- 926 Reference< XInterface > SAL_CALL OConnection::getTableEditor( const Reference< XDatabaseDocumentUI >& _DocumentUI, const ::rtl::OUString& _TableName ) 927 { 928 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dataaccess", "Ocke.Janssen@sun.com", "OConnection::getTableEditor" ); 929 Reference< XInterface > xReturn; 930 931 // ask our aggregate 932 if ( m_xTableUIProvider.is() ) 933 xReturn = m_xTableUIProvider->getTableEditor( _DocumentUI, _TableName ); 934 935 // ask ourself 936 // well, we don't have own functionality here ... 937 // In the future, we might decide to delegate the complete handling to this interface. 938 // In this case, we would need to instantiate an css.sdb.TableDesign here. 939 940 return xReturn; 941 } 942 943 944 //........................................................................ 945 } // namespace dbaccess 946 //........................................................................ 947