Branch data 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 : :
21 : : #include "connectivity/dbmetadata.hxx"
22 : : #include "connectivity/dbexception.hxx"
23 : : #include "connectivity/DriversConfig.hxx"
24 : : #include "resource/common_res.hrc"
25 : : #include "resource/sharedresources.hxx"
26 : :
27 : : #include <com/sun/star/lang/IllegalArgumentException.hpp>
28 : : #include <com/sun/star/container/XChild.hpp>
29 : : #include <com/sun/star/beans/XPropertySet.hpp>
30 : : #include <com/sun/star/beans/PropertyValue.hpp>
31 : : #include <com/sun/star/beans/XPropertySetInfo.hpp>
32 : : #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
33 : : #include <com/sun/star/sdbc/XDatabaseMetaData2.hpp>
34 : : #include <com/sun/star/sdbcx/XUsersSupplier.hpp>
35 : : #include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp>
36 : : #include <com/sun/star/sdbc/XDriverAccess.hpp>
37 : :
38 : : #include <tools/diagnose_ex.h>
39 : : #include <comphelper/namedvaluecollection.hxx>
40 : : #include <comphelper/componentcontext.hxx>
41 : : #include <comphelper/processfactory.hxx>
42 : : #include <sal/macros.h>
43 : :
44 : : #include <boost/optional.hpp>
45 : :
46 : : //........................................................................
47 : : namespace dbtools
48 : : {
49 : : //........................................................................
50 : :
51 : : /** === begin UNO using === **/
52 : : using ::com::sun::star::uno::Reference;
53 : : using ::com::sun::star::sdbc::XConnection;
54 : : using ::com::sun::star::sdbc::XConnection;
55 : : using ::com::sun::star::sdbc::XDatabaseMetaData;
56 : : using ::com::sun::star::sdbc::XDatabaseMetaData2;
57 : : using ::com::sun::star::lang::IllegalArgumentException;
58 : : using ::com::sun::star::uno::Exception;
59 : : using ::com::sun::star::uno::Any;
60 : : using ::com::sun::star::container::XChild;
61 : : using ::com::sun::star::uno::UNO_QUERY_THROW;
62 : : using ::com::sun::star::beans::XPropertySet;
63 : : using ::com::sun::star::uno::Sequence;
64 : : using ::com::sun::star::beans::PropertyValue;
65 : : using ::com::sun::star::beans::XPropertySetInfo;
66 : : using ::com::sun::star::uno::UNO_QUERY;
67 : : using ::com::sun::star::sdbcx::XUsersSupplier;
68 : : using ::com::sun::star::sdbcx::XDataDefinitionSupplier;
69 : : using ::com::sun::star::sdbc::XDriverAccess;
70 : : using ::com::sun::star::uno::UNO_SET_THROW;
71 : : /** === end UNO using === **/
72 : : namespace BooleanComparisonMode = ::com::sun::star::sdb::BooleanComparisonMode;
73 : :
74 : : //====================================================================
75 : : //= DatabaseMetaData_Impl
76 : : //====================================================================
77 [ + - ][ + - ]: 47186 : struct DatabaseMetaData_Impl
[ + - ][ + - ]
[ + - ][ + - ]
78 : : {
79 : : Reference< XConnection > xConnection;
80 : : Reference< XDatabaseMetaData > xConnectionMetaData;
81 : : ::connectivity::DriversConfig aDriverConfig;
82 : :
83 : : ::boost::optional< ::rtl::OUString > sCachedIdentifierQuoteString;
84 : : ::boost::optional< ::rtl::OUString > sCachedCatalogSeparator;
85 : :
86 : 3546 : DatabaseMetaData_Impl()
87 : : :xConnection()
88 : : ,xConnectionMetaData()
89 : : ,aDriverConfig( ::comphelper::getProcessServiceFactory() )
90 : : ,sCachedIdentifierQuoteString()
91 [ + - ][ + - ]: 3546 : ,sCachedCatalogSeparator()
[ + - ][ + - ]
92 : : {
93 : 3546 : }
94 : : };
95 : :
96 : : //--------------------------------------------------------------------
97 : : namespace
98 : : {
99 : : //................................................................
100 : 3546 : static void lcl_construct( DatabaseMetaData_Impl& _metaDataImpl, const Reference< XConnection >& _connection )
101 : : {
102 : 3546 : _metaDataImpl.xConnection = _connection;
103 [ - + ]: 3546 : if ( !_metaDataImpl.xConnection.is() )
104 : 3546 : return;
105 : :
106 [ + - ]: 3546 : _metaDataImpl.xConnectionMetaData = _connection->getMetaData();
107 [ - + ]: 3546 : if ( !_metaDataImpl.xConnectionMetaData.is() )
108 [ # # ]: 0 : throw IllegalArgumentException();
109 : : }
110 : :
111 : : //................................................................
112 : 9078 : static void lcl_checkConnected( const DatabaseMetaData_Impl& _metaDataImpl )
113 : : {
114 [ + - ][ - + ]: 9078 : if ( !_metaDataImpl.xConnection.is() || !_metaDataImpl.xConnectionMetaData.is() )
[ - + ]
115 : : {
116 [ # # ]: 0 : ::connectivity::SharedResources aResources;
117 [ # # ]: 0 : const ::rtl::OUString sError( aResources.getResourceString(STR_NO_CONNECTION_GIVEN));
118 [ # # ][ # # ]: 0 : throwSQLException( sError, SQL_CONNECTION_DOES_NOT_EXIST, NULL );
[ # # ]
119 : : }
120 : 9078 : }
121 : :
122 : : //................................................................
123 : 0 : static bool lcl_getDriverSetting( const sal_Char* _asciiName, const DatabaseMetaData_Impl& _metaData, Any& _out_setting )
124 : : {
125 : 0 : lcl_checkConnected( _metaData );
126 [ # # ]: 0 : const ::comphelper::NamedValueCollection& rDriverMetaData = _metaData.aDriverConfig.getMetaData( _metaData.xConnectionMetaData->getURL() );
127 [ # # ]: 0 : if ( !rDriverMetaData.has( _asciiName ) )
128 : 0 : return false;
129 : 0 : _out_setting = rDriverMetaData.get( _asciiName );
130 : 0 : return true;
131 : : }
132 : :
133 : : //................................................................
134 : 0 : static bool lcl_getConnectionSetting( const sal_Char* _asciiName, const DatabaseMetaData_Impl& _metaData, Any& _out_setting )
135 : : {
136 : : try
137 : : {
138 [ # # ]: 0 : Reference< XChild > xConnectionAsChild( _metaData.xConnection, UNO_QUERY );
139 [ # # ]: 0 : if ( xConnectionAsChild.is() )
140 : : {
141 [ # # ][ # # ]: 0 : Reference< XPropertySet > xDataSource( xConnectionAsChild->getParent(), UNO_QUERY_THROW );
[ # # ]
142 : : Reference< XPropertySet > xDataSourceSettings(
143 [ # # ]: 0 : xDataSource->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Settings" ) ) ),
144 [ # # ][ # # ]: 0 : UNO_QUERY_THROW );
[ # # ]
145 : :
146 [ # # ][ # # ]: 0 : _out_setting = xDataSourceSettings->getPropertyValue( ::rtl::OUString::createFromAscii( _asciiName ) );
147 : : }
148 : : else
149 : : {
150 [ # # ]: 0 : Reference< XDatabaseMetaData2 > xExtendedMetaData( _metaData.xConnectionMetaData, UNO_QUERY_THROW );
151 [ # # ][ # # ]: 0 : ::comphelper::NamedValueCollection aSettings( xExtendedMetaData->getConnectionInfo() );
[ # # ][ # # ]
152 [ # # ]: 0 : _out_setting = aSettings.get( _asciiName );
153 [ # # ]: 0 : return _out_setting.hasValue();
154 : : }
155 [ # # ]: 0 : return true;
156 : : }
157 : 0 : catch( const Exception& )
158 : : {
159 : : DBG_UNHANDLED_EXCEPTION();
160 : : }
161 : 0 : return false;
162 : : }
163 : :
164 : : //................................................................
165 : 11234 : static const ::rtl::OUString& lcl_getConnectionStringSetting(
166 : : const DatabaseMetaData_Impl& _metaData, ::boost::optional< ::rtl::OUString >& _cachedSetting,
167 : : ::rtl::OUString (SAL_CALL XDatabaseMetaData::*_getter)() )
168 : : {
169 [ + + ]: 11234 : if ( !_cachedSetting )
170 : : {
171 : 8628 : lcl_checkConnected( _metaData );
172 : : try
173 : : {
174 [ - + ][ + - ]: 8628 : _cachedSetting.reset( (_metaData.xConnectionMetaData.get()->*_getter)() );
[ + - ][ # # ]
[ + - ]
175 : : }
176 : 0 : catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
177 : : }
178 : 11234 : return *_cachedSetting;
179 : : }
180 : : }
181 : :
182 : : //====================================================================
183 : : //= DatabaseMetaData
184 : : //====================================================================
185 : : //--------------------------------------------------------------------
186 : 0 : DatabaseMetaData::DatabaseMetaData()
187 [ # # ]: 0 : :m_pImpl( new DatabaseMetaData_Impl )
188 : : {
189 : 0 : }
190 : :
191 : : //--------------------------------------------------------------------
192 : 3546 : DatabaseMetaData::DatabaseMetaData( const Reference< XConnection >& _connection )
193 [ + - ]: 3546 : :m_pImpl( new DatabaseMetaData_Impl )
194 : : {
195 [ + - ]: 3546 : lcl_construct( *m_pImpl, _connection );
196 : 3546 : }
197 : :
198 : : //--------------------------------------------------------------------
199 : 21820 : DatabaseMetaData::DatabaseMetaData( const DatabaseMetaData& _copyFrom )
200 [ + - ]: 21820 : :m_pImpl( new DatabaseMetaData_Impl( *_copyFrom.m_pImpl ) )
201 : : {
202 : 21820 : }
203 : :
204 : : //--------------------------------------------------------------------
205 : 0 : DatabaseMetaData& DatabaseMetaData::operator=( const DatabaseMetaData& _copyFrom )
206 : : {
207 [ # # ]: 0 : if ( this == &_copyFrom )
208 : 0 : return *this;
209 : :
210 [ # # ]: 0 : m_pImpl.reset( new DatabaseMetaData_Impl( *_copyFrom.m_pImpl ) );
211 : 0 : return *this;
212 : : }
213 : :
214 : : //--------------------------------------------------------------------
215 : 25366 : DatabaseMetaData::~DatabaseMetaData()
216 : : {
217 : 25366 : }
218 : :
219 : : //--------------------------------------------------------------------
220 : 0 : bool DatabaseMetaData::isConnected() const
221 : : {
222 : 0 : return m_pImpl->xConnection.is();
223 : : }
224 : :
225 : : //--------------------------------------------------------------------
226 : 450 : bool DatabaseMetaData::supportsSubqueriesInFrom() const
227 : : {
228 : 450 : lcl_checkConnected( *m_pImpl );
229 : :
230 : 450 : bool supportsSubQueries = false;
231 : : try
232 : : {
233 [ + - ][ + - ]: 450 : sal_Int32 maxTablesInselect = m_pImpl->xConnectionMetaData->getMaxTablesInSelect();
234 [ + - ][ - + ]: 450 : supportsSubQueries = ( maxTablesInselect > 1 ) || ( maxTablesInselect == 0 );
235 : : // TODO: is there a better way to determine this? The above is not really true. More precise,
236 : : // it's a *very* generous heuristics ...
237 : : }
238 : 0 : catch( const Exception& )
239 : : {
240 : : DBG_UNHANDLED_EXCEPTION();
241 : : }
242 [ # # ]: 450 : return supportsSubQueries;
243 : : }
244 : :
245 : : //--------------------------------------------------------------------
246 : 0 : bool DatabaseMetaData::supportsPrimaryKeys() const
247 : : {
248 [ # # ]: 0 : lcl_checkConnected( *m_pImpl );
249 : :
250 : 0 : bool doesSupportPrimaryKeys = false;
251 : : try
252 : : {
253 : 0 : Any setting;
254 [ # # # # ]: 0 : if ( !( lcl_getConnectionSetting( "PrimaryKeySupport", *m_pImpl, setting ) )
[ # # ][ # # ]
255 : 0 : || !( setting >>= doesSupportPrimaryKeys )
256 : : )
257 [ # # ][ # # ]: 0 : doesSupportPrimaryKeys = m_pImpl->xConnectionMetaData->supportsCoreSQLGrammar();
[ # # ]
258 : : }
259 [ # # ]: 0 : catch( const Exception& )
260 : : {
261 : : DBG_UNHANDLED_EXCEPTION();
262 : : }
263 : 0 : return doesSupportPrimaryKeys;
264 : : }
265 : :
266 : : //--------------------------------------------------------------------
267 : 5212 : const ::rtl::OUString& DatabaseMetaData::getIdentifierQuoteString() const
268 : : {
269 : 5212 : return lcl_getConnectionStringSetting( *m_pImpl, m_pImpl->sCachedIdentifierQuoteString, &XDatabaseMetaData::getIdentifierQuoteString );
270 : : }
271 : :
272 : : //--------------------------------------------------------------------
273 : 6022 : const ::rtl::OUString& DatabaseMetaData::getCatalogSeparator() const
274 : : {
275 : 6022 : return lcl_getConnectionStringSetting( *m_pImpl, m_pImpl->sCachedCatalogSeparator, &XDatabaseMetaData::getCatalogSeparator );
276 : : }
277 : :
278 : : //--------------------------------------------------------------------
279 : 0 : bool DatabaseMetaData::restrictIdentifiersToSQL92() const
280 : : {
281 [ # # ]: 0 : lcl_checkConnected( *m_pImpl );
282 : :
283 : 0 : bool restrict( false );
284 : 0 : Any setting;
285 [ # # ][ # # ]: 0 : if ( lcl_getConnectionSetting( "EnableSQL92Check", *m_pImpl, setting ) )
286 : 0 : OSL_VERIFY( setting >>= restrict );
287 : 0 : return restrict;
288 : : }
289 : :
290 : : //--------------------------------------------------------------------
291 : 0 : bool DatabaseMetaData::generateASBeforeCorrelationName() const
292 : : {
293 : 0 : bool doGenerate( true );
294 : 0 : Any setting;
295 [ # # ][ # # ]: 0 : if ( lcl_getConnectionSetting( "GenerateASBeforeCorrelationName", *m_pImpl, setting ) )
296 : 0 : OSL_VERIFY( setting >>= doGenerate );
297 : 0 : return doGenerate;
298 : : }
299 : : //--------------------------------------------------------------------
300 : 0 : bool DatabaseMetaData::shouldEscapeDateTime() const
301 : : {
302 : 0 : bool doGenerate( true );
303 : 0 : Any setting;
304 [ # # ][ # # ]: 0 : if ( lcl_getConnectionSetting( "EscapeDateTime", *m_pImpl, setting ) )
305 : 0 : OSL_VERIFY( setting >>= doGenerate );
306 : 0 : return doGenerate;
307 : : }
308 : : //--------------------------------------------------------------------
309 : 0 : bool DatabaseMetaData::isAutoIncrementPrimaryKey() const
310 : : {
311 : 0 : bool is( true );
312 : 0 : Any setting;
313 [ # # ][ # # ]: 0 : if ( lcl_getDriverSetting( "AutoIncrementIsPrimaryKey", *m_pImpl, setting ) )
314 : 0 : OSL_VERIFY( setting >>= is );
315 : 0 : return is;
316 : : }
317 : : //--------------------------------------------------------------------
318 : 0 : sal_Int32 DatabaseMetaData::getBooleanComparisonMode() const
319 : : {
320 : 0 : sal_Int32 mode( BooleanComparisonMode::EQUAL_INTEGER );
321 : 0 : Any setting;
322 [ # # ][ # # ]: 0 : if ( lcl_getConnectionSetting( "BooleanComparisonMode", *m_pImpl, setting ) )
323 : 0 : OSL_VERIFY( setting >>= mode );
324 : 0 : return mode;
325 : : }
326 : : //--------------------------------------------------------------------
327 : 0 : bool DatabaseMetaData::supportsRelations() const
328 : : {
329 : 0 : lcl_checkConnected( *m_pImpl );
330 : 0 : bool bSupport = false;
331 : : try
332 : : {
333 [ # # ][ # # ]: 0 : bSupport = m_pImpl->xConnectionMetaData->supportsIntegrityEnhancementFacility();
334 : : }
335 [ # # ]: 0 : catch( const Exception& )
336 : : {
337 : : DBG_UNHANDLED_EXCEPTION();
338 : : }
339 : : try
340 : : {
341 [ # # ]: 0 : if ( !bSupport )
342 : : {
343 [ # # ][ # # ]: 0 : const ::rtl::OUString url = m_pImpl->xConnectionMetaData->getURL();
344 : 0 : char pMySQL[] = "sdbc:mysql";
345 : 0 : bSupport = url.matchAsciiL(pMySQL,(sizeof(pMySQL)/sizeof(pMySQL[0]))-1);
346 : : }
347 : : }
348 : 0 : catch( const Exception& )
349 : : {
350 : : DBG_UNHANDLED_EXCEPTION();
351 : : }
352 [ # # ]: 0 : return bSupport;
353 : : }
354 : :
355 : : //--------------------------------------------------------------------
356 : 0 : bool DatabaseMetaData::supportsColumnAliasInOrderBy() const
357 : : {
358 : 0 : bool doGenerate( true );
359 : 0 : Any setting;
360 [ # # ][ # # ]: 0 : if ( lcl_getConnectionSetting( "ColumnAliasInOrderBy", *m_pImpl, setting ) )
361 : 0 : OSL_VERIFY( setting >>= doGenerate );
362 : 0 : return doGenerate;
363 : : }
364 : :
365 : : //--------------------------------------------------------------------
366 : 0 : bool DatabaseMetaData::supportsUserAdministration( const ::comphelper::ComponentContext& _rContext ) const
367 : : {
368 : 0 : lcl_checkConnected( *m_pImpl );
369 : :
370 : 0 : bool isSupported( false );
371 : : try
372 : : {
373 : : // find the XUsersSupplier interface
374 : : // - either directly at the connection
375 [ # # ]: 0 : Reference< XUsersSupplier > xUsersSupp( m_pImpl->xConnection, UNO_QUERY );
376 [ # # ]: 0 : if ( !xUsersSupp.is() )
377 : : {
378 : : // - or at the driver manager
379 : : Reference< XDriverAccess > xDriverManager(
380 [ # # ][ # # ]: 0 : _rContext.createComponent( "com.sun.star.sdbc.DriverManager" ), UNO_QUERY_THROW );
381 [ # # ][ # # ]: 0 : Reference< XDataDefinitionSupplier > xDriver( xDriverManager->getDriverByURL( m_pImpl->xConnectionMetaData->getURL() ), UNO_QUERY );
[ # # ][ # # ]
[ # # ]
382 [ # # ]: 0 : if ( xDriver.is() )
383 [ # # ][ # # ]: 0 : xUsersSupp.set( xDriver->getDataDefinitionByConnection( m_pImpl->xConnection ), UNO_QUERY );
[ # # ]
384 : : }
385 : :
386 [ # # ][ # # ]: 0 : isSupported = ( xUsersSupp.is() && xUsersSupp->getUsers().is() );
[ # # ][ # # ]
[ # # ]
[ # # # # ]
387 : : }
388 : 0 : catch( const Exception& )
389 : : {
390 : : DBG_UNHANDLED_EXCEPTION();
391 : : }
392 : 0 : return isSupported;
393 : : }
394 : :
395 : : //--------------------------------------------------------------------
396 : 0 : bool DatabaseMetaData::displayEmptyTableFolders() const
397 : : {
398 : 0 : bool doDisplay( true );
399 : : #ifdef IMPLEMENTED_LATER
400 : : Any setting;
401 : : if ( lcl_getConnectionSetting( "DisplayEmptyTableFolders", *m_pImpl, setting ) )
402 : : OSL_VERIFY( setting >>= doDisplay );
403 : : #else
404 : : try
405 : : {
406 [ # # ]: 0 : Reference< XDatabaseMetaData > xMeta( m_pImpl->xConnectionMetaData, UNO_SET_THROW );
407 [ # # ][ # # ]: 0 : ::rtl::OUString sConnectionURL( xMeta->getURL() );
408 [ # # ]: 0 : doDisplay = sConnectionURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:mysqlc" ) ) == 0;
409 : : }
410 : 0 : catch( const Exception& )
411 : : {
412 : : DBG_UNHANDLED_EXCEPTION();
413 : : }
414 : : #endif
415 : 0 : return doDisplay;
416 : : }
417 : : //--------------------------------------------------------------------
418 : 0 : bool DatabaseMetaData::supportsThreads() const
419 : : {
420 : 0 : bool bSupported( true );
421 : : try
422 : : {
423 [ # # ]: 0 : Reference< XDatabaseMetaData > xMeta( m_pImpl->xConnectionMetaData, UNO_SET_THROW );
424 [ # # ][ # # ]: 0 : ::rtl::OUString sConnectionURL( xMeta->getURL() );
425 [ # # ]: 0 : bSupported = sConnectionURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:mysqlc" ) ) != 0;
426 : : }
427 : 0 : catch( const Exception& )
428 : : {
429 : : DBG_UNHANDLED_EXCEPTION();
430 : : }
431 : 0 : return bSupported;
432 : : }
433 : :
434 : : //........................................................................
435 : : } // namespace dbtools
436 : : //........................................................................
437 : :
438 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|