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