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 //------------------------------------------------------------------------------
getImplementationName()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 //------------------------------------------------------------------------------
supportsService(const::rtl::OUString & _rServiceName)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 //------------------------------------------------------------------------------
getSupportedServiceNames()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 //------------------------------------------------------------------------------
close(void)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 //------------------------------------------------------------------------------
isClosed(void)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 //------------------------------------------------------------------------------
createStatement(void)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 //------------------------------------------------------------------------------
prepareStatement(const rtl::OUString & sql)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 //------------------------------------------------------------------------------
prepareCall(const rtl::OUString & sql)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 //------------------------------------------------------------------------------
nativeSQL(const rtl::OUString & sql)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 //------------------------------------------------------------------------------
setAutoCommit(sal_Bool autoCommit)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 //------------------------------------------------------------------------------
getAutoCommit(void)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 //------------------------------------------------------------------------------
commit(void)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 //------------------------------------------------------------------------------
rollback(void)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 //------------------------------------------------------------------------------
getMetaData(void)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 //------------------------------------------------------------------------------
setReadOnly(sal_Bool readOnly)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 //------------------------------------------------------------------------------
isReadOnly(void)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 //------------------------------------------------------------------------------
setCatalog(const rtl::OUString & catalog)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 //------------------------------------------------------------------------------
getCatalog(void)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 //------------------------------------------------------------------------------
setTransactionIsolation(sal_Int32 level)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 //------------------------------------------------------------------------------
getTransactionIsolation(void)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 //------------------------------------------------------------------------------
getTypeMap(void)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 //------------------------------------------------------------------------------
setTypeMap(const Reference<XNameAccess> & typeMap)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 //==========================================================================
DBG_NAME(OConnection)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 //--------------------------------------------------------------------------
~OConnection()419 OConnection::~OConnection()
420 {
421 delete m_pTables;
422 delete m_pViews;
423 DBG_DTOR(OConnection,NULL);
424 }
425
426
427 // XWarningsSupplier
428 //--------------------------------------------------------------------------
getWarnings()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 //--------------------------------------------------------------------------
clearWarnings()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 {
operator ()dbaccess::__anon85d42f010111::CompareTypeByName451 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
lcl_copyTypes(TypeBag & _out_rTypes,const Sequence<Type> & _rTypes)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 //--------------------------------------------------------------------------
getTypes()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 //--------------------------------------------------------------------------
getImplementationId()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 //--------------------------------------------------------------------------
queryInterface(const Type & rType)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 //--------------------------------------------------------------------------
acquire()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 //--------------------------------------------------------------------------
release()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 //------------------------------------------------------------------------------
disposing()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 //------------------------------------------------------------------------------
getParent(void)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 //------------------------------------------------------------------------------
setParent(const Reference<XInterface> &)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 //------------------------------------------------------------------------------
createQueryComposer(void)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 // -----------------------------------------------------------------------------
impl_fillTableFilter()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 // -----------------------------------------------------------------------------
refresh(const Reference<XNameAccess> & _rToBeRefreshed)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 //------------------------------------------------------------------------------
getTables()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 // -----------------------------------------------------------------------------
getViews()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 //------------------------------------------------------------------------------
getQueries(void)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 //------------------------------------------------------------------------------
prepareCommand(const::rtl::OUString & command,sal_Int32 commandType)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 // -----------------------------------------------------------------------------
createInstance(const::rtl::OUString & _sServiceSpecifier)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 // -----------------------------------------------------------------------------
createInstanceWithArguments(const::rtl::OUString & _sServiceSpecifier,const Sequence<Any> &)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 // -----------------------------------------------------------------------------
getAvailableServiceNames()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 // -----------------------------------------------------------------------------
getMasterTables()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
getUsers()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
getGroups()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 // -----------------------------------------------------------------------------
impl_loadConnectionTools_throw()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 // -----------------------------------------------------------------------------
createTableName()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 // -----------------------------------------------------------------------------
getObjectNames()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 // -----------------------------------------------------------------------------
getDataSourceMetaData()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 // -----------------------------------------------------------------------------
getFieldsByCommandDescriptor(::sal_Int32 commandType,const::rtl::OUString & command,::com::sun::star::uno::Reference<::com::sun::star::lang::XComponent> & keepFieldsAlive)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 //--------------------------------------------------------------------
getComposer(::sal_Int32 commandType,const::rtl::OUString & command)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 // -----------------------------------------------------------------------------
impl_checkTableQueryNames_nothrow()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 // -----------------------------------------------------------------------------
getTableIcon(const::rtl::OUString & _TableName,::sal_Int32 _ColorMode)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 // -----------------------------------------------------------------------------
getTableEditor(const Reference<XDatabaseDocumentUI> & _DocumentUI,const::rtl::OUString & _TableName)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