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