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