LibreOffice Module connectivity (master) 1
dbmetadata.cxx
Go to the documentation of this file.
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
24#include <strings.hrc>
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/sdb/BooleanComparisonMode.hpp>
31#include <com/sun/star/sdbc/XDatabaseMetaData2.hpp>
32#include <com/sun/star/sdbcx/XUsersSupplier.hpp>
33#include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp>
34#include <com/sun/star/sdbc/DriverManager.hpp>
35
39#include <sal/log.hxx>
40
41#include <optional>
42
43
44namespace dbtools
45{
46
47
48 using ::com::sun::star::uno::Reference;
49 using ::com::sun::star::sdbc::XConnection;
50 using ::com::sun::star::sdbc::XDatabaseMetaData;
51 using ::com::sun::star::sdbc::XDatabaseMetaData2;
52 using ::com::sun::star::lang::IllegalArgumentException;
53 using ::com::sun::star::uno::Exception;
54 using ::com::sun::star::uno::Any;
55 using ::com::sun::star::uno::XComponentContext;
56 using ::com::sun::star::container::XChild;
57 using ::com::sun::star::uno::UNO_QUERY_THROW;
58 using ::com::sun::star::beans::XPropertySet;
59 using ::com::sun::star::uno::UNO_QUERY;
60 using ::com::sun::star::sdbcx::XUsersSupplier;
61 using ::com::sun::star::sdbcx::XDataDefinitionSupplier;
62 using ::com::sun::star::sdbc::DriverManager;
63 using ::com::sun::star::sdbc::XDriverManager2;
64 using ::com::sun::star::uno::UNO_SET_THROW;
65
66 namespace BooleanComparisonMode = ::com::sun::star::sdb::BooleanComparisonMode;
67
69 {
70 Reference< XConnection > xConnection;
71 Reference< XDatabaseMetaData > xConnectionMetaData;
73
74 ::std::optional< OUString > sCachedIdentifierQuoteString;
75 ::std::optional< OUString > sCachedCatalogSeparator;
76
79 {
80 }
81 };
82
83
84 namespace
85 {
86
87 void lcl_construct( DatabaseMetaData_Impl& _metaDataImpl, const Reference< XConnection >& _connection )
88 {
89 _metaDataImpl.xConnection = _connection;
90 if ( !_metaDataImpl.xConnection.is() )
91 return;
92
93 _metaDataImpl.xConnectionMetaData = _connection->getMetaData();
94 if ( !_metaDataImpl.xConnectionMetaData.is() )
95 throw IllegalArgumentException();
96 }
97
98
99 void lcl_checkConnected( const DatabaseMetaData_Impl& _metaDataImpl )
100 {
101 if ( !_metaDataImpl.xConnection.is() || !_metaDataImpl.xConnectionMetaData.is() )
102 {
104 const OUString sError( aResources.getResourceString(STR_NO_CONNECTION_GIVEN));
106 }
107 }
108
109
110 bool lcl_getDriverSetting( const OUString& _asciiName, const DatabaseMetaData_Impl& _metaData, Any& _out_setting )
111 {
112 lcl_checkConnected( _metaData );
113 const ::comphelper::NamedValueCollection& rDriverMetaData = _metaData.aDriverConfig.getMetaData( _metaData.xConnectionMetaData->getURL() );
114 if ( !rDriverMetaData.has( _asciiName ) )
115 return false;
116 _out_setting = rDriverMetaData.get( _asciiName );
117 return true;
118 }
119
120
121 bool lcl_getConnectionSetting(const OUString& _asciiName, const DatabaseMetaData_Impl& _metaData, Any& _out_setting )
122 {
123 try
124 {
125 Reference< XChild > xConnectionAsChild( _metaData.xConnection, UNO_QUERY );
126 if ( xConnectionAsChild.is() )
127 {
128 Reference< XPropertySet > xDataSource( xConnectionAsChild->getParent(), UNO_QUERY_THROW );
129 Reference< XPropertySet > xDataSourceSettings(
130 xDataSource->getPropertyValue("Settings"),
131 UNO_QUERY_THROW );
132
133 _out_setting = xDataSourceSettings->getPropertyValue( _asciiName );
134 }
135 else
136 {
137 Reference< XDatabaseMetaData2 > xExtendedMetaData( _metaData.xConnectionMetaData, UNO_QUERY_THROW );
138 _out_setting = ::comphelper::NamedValueCollection::get( xExtendedMetaData->getConnectionInfo(), _asciiName );
139 return _out_setting.hasValue();
140 }
141 return true;
142 }
143 catch( const Exception& )
144 {
145 DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
146 }
147 return false;
148 }
149
150
151 const OUString& lcl_getConnectionStringSetting(
152 const DatabaseMetaData_Impl& _metaData, ::std::optional< OUString >& _cachedSetting,
153 OUString (SAL_CALL XDatabaseMetaData::*_getter)() )
154 {
155 if ( !_cachedSetting )
156 {
157 lcl_checkConnected( _metaData );
158 try
159 {
160 _cachedSetting = (_metaData.xConnectionMetaData.get()->*_getter)();
161 }
162 catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("connectivity.commontools"); }
163 }
164 return *_cachedSetting;
165 }
166 }
167
170 {
171 }
172
173 DatabaseMetaData::DatabaseMetaData( const Reference< XConnection >& _connection )
175 {
176 lcl_construct( *m_pImpl, _connection );
177 }
178
179
181 :m_pImpl( new DatabaseMetaData_Impl( *_copyFrom.m_pImpl ) )
182 {
183 }
184
186 :m_pImpl(std::move(_copyFrom.m_pImpl))
187 {
188 }
189
191 {
192 if ( this == &_copyFrom )
193 return *this;
194
195 m_pImpl.reset( new DatabaseMetaData_Impl( *_copyFrom.m_pImpl ) );
196 return *this;
197 }
198
200 {
201 m_pImpl = std::move(_copyFrom.m_pImpl);
202 return *this;
203 }
204
206 {
207 }
208
210 {
211 return m_pImpl->xConnection.is();
212 }
213
214
216 {
217 lcl_checkConnected( *m_pImpl );
218
219 bool bSupportsSubQueries = false;
220 try
221 {
222 sal_Int32 maxTablesInselect = m_pImpl->xConnectionMetaData->getMaxTablesInSelect();
223 bSupportsSubQueries = ( maxTablesInselect > 1 ) || ( maxTablesInselect == 0 );
224 // TODO: is there a better way to determine this? The above is not really true. More precise,
225 // it's a *very* generous heuristics ...
226 }
227 catch( const Exception& )
228 {
229 DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
230 }
231 return bSupportsSubQueries;
232 }
233
234
236 {
237 lcl_checkConnected( *m_pImpl );
238
239 bool bDoesSupportPrimaryKeys = false;
240 try
241 {
242 Any setting;
243 if ( !( lcl_getConnectionSetting( "PrimaryKeySupport", *m_pImpl, setting ) )
244 || !( setting >>= bDoesSupportPrimaryKeys )
245 )
246 bDoesSupportPrimaryKeys = m_pImpl->xConnectionMetaData->supportsCoreSQLGrammar()
247 || m_pImpl->xConnectionMetaData->supportsANSI92EntryLevelSQL();
248 }
249 catch( const Exception& )
250 {
251 DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
252 }
253 return bDoesSupportPrimaryKeys;
254 }
255
256
258 {
259 return lcl_getConnectionStringSetting( *m_pImpl, m_pImpl->sCachedIdentifierQuoteString, &XDatabaseMetaData::getIdentifierQuoteString );
260 }
261
262
264 {
265 return lcl_getConnectionStringSetting( *m_pImpl, m_pImpl->sCachedCatalogSeparator, &XDatabaseMetaData::getCatalogSeparator );
266 }
267
268
270 {
271 lcl_checkConnected( *m_pImpl );
272
273 bool restrict( false );
274 Any setting;
275 if ( lcl_getConnectionSetting( "EnableSQL92Check", *m_pImpl, setting ) )
276 if( ! (setting >>= restrict) )
277 SAL_WARN("connectivity.commontools", "restrictIdentifiersToSQL92: unable to assign EnableSQL92Check");
278 return restrict;
279 }
280
281
283 {
284 bool doGenerate( false );
285 Any setting;
286 if ( lcl_getConnectionSetting( "GenerateASBeforeCorrelationName", *m_pImpl, setting ) )
287 if( ! (setting >>= doGenerate) )
288 SAL_WARN("connectivity.commontools", "generateASBeforeCorrelationName: unable to assign GenerateASBeforeCorrelationName");
289 return doGenerate;
290 }
291
293 {
294 bool doGenerate( true );
295 Any setting;
296 if ( lcl_getConnectionSetting( "EscapeDateTime", *m_pImpl, setting ) )
297 if( ! (setting >>= doGenerate) )
298 SAL_WARN("connectivity.commontools", "shouldEscapeDateTime: unable to assign EscapeDateTime");
299 return doGenerate;
300 }
301
303 {
304 bool doSubstitute( true );
305 Any setting;
306 if ( lcl_getConnectionSetting( "ParameterNameSubstitution", *m_pImpl, setting ) )
307 if( ! (setting >>= doSubstitute) )
308 SAL_WARN("connectivity.commontools", "shouldSubstituteParameterNames: unable to assign ParameterNameSubstitution");
309 return doSubstitute;
310 }
311
313 {
314 bool is( true );
315 Any setting;
316 if ( lcl_getDriverSetting( "AutoIncrementIsPrimaryKey", *m_pImpl, setting ) )
317 if( ! (setting >>= is) )
318 SAL_WARN("connectivity.commontools", "isAutoIncrementPrimaryKey: unable to assign AutoIncrementIsPrimaryKey");
319 return is;
320 }
321
323 {
324 sal_Int32 mode( BooleanComparisonMode::EQUAL_INTEGER );
325 Any setting;
326 if ( lcl_getConnectionSetting( "BooleanComparisonMode", *m_pImpl, setting ) )
327 if( ! (setting >>= mode) )
328 SAL_WARN("connectivity.commontools", "getBooleanComparisonMode: unable to assign BooleanComparisonMode");
329 return mode;
330 }
331
333 {
334 lcl_checkConnected( *m_pImpl );
335 bool bSupport = false;
336 try
337 {
338 bSupport = m_pImpl->xConnectionMetaData->supportsIntegrityEnhancementFacility();
339 }
340 catch( const Exception& )
341 {
342 DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
343 }
344 try
345 {
346 if ( !bSupport )
347 {
348 const OUString url = m_pImpl->xConnectionMetaData->getURL();
349 bSupport = url.startsWith("sdbc:mysql");
350 }
351 }
352 catch( const Exception& )
353 {
354 DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
355 }
356 return bSupport;
357 }
358
359
361 {
362 bool doGenerate( true );
363 Any setting;
364 if ( lcl_getConnectionSetting( "ColumnAliasInOrderBy", *m_pImpl, setting ) )
365 if( ! (setting >>= doGenerate) )
366 SAL_WARN("connectivity.commontools", "supportsColumnAliasInOrderBy: unable to assign ColumnAliasInOrderBy");
367 return doGenerate;
368 }
369
370
371 bool DatabaseMetaData::supportsUserAdministration( const Reference<XComponentContext>& _rContext ) const
372 {
373 lcl_checkConnected( *m_pImpl );
374
375 bool isSupported( false );
376 try
377 {
378 // find the XUsersSupplier interface
379 // - either directly at the connection
380 Reference< XUsersSupplier > xUsersSupp( m_pImpl->xConnection, UNO_QUERY );
381 if ( !xUsersSupp.is() )
382 {
383 // - or at the driver manager
384 Reference< XDriverManager2 > xDriverManager = DriverManager::create( _rContext );
385 Reference< XDataDefinitionSupplier > xDriver( xDriverManager->getDriverByURL( m_pImpl->xConnectionMetaData->getURL() ), UNO_QUERY );
386 if ( xDriver.is() )
387 xUsersSupp.set( xDriver->getDataDefinitionByConnection( m_pImpl->xConnection ), UNO_QUERY );
388 }
389
390 isSupported = ( xUsersSupp.is() && xUsersSupp->getUsers().is() );
391 }
392 catch( const Exception& )
393 {
394 DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
395 }
396 return isSupported;
397 }
398
399
401 {
402 bool doDisplay( true );
403#ifdef IMPLEMENTED_LATER
404 Any setting;
405 if ( lcl_getConnectionSetting( "DisplayEmptyTableFolders", *m_pImpl, setting ) )
406 if( ! (setting >>= doDisplay) )
407 SAL_WARN("connectivity.commontools", "displayEmptyTableFolders: unable to assign DisplayEmptyTableFolders");
408#else
409 try
410 {
411 Reference< XDatabaseMetaData > xMeta( m_pImpl->xConnectionMetaData, UNO_SET_THROW );
412 OUString sConnectionURL( xMeta->getURL() );
413 doDisplay = sConnectionURL.startsWith( "sdbc:mysql:mysqlc" );
414 }
415 catch( const Exception& )
416 {
417 DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
418 }
419#endif
420 return doDisplay;
421 }
422
424 {
425 bool bSupported( true );
426 try
427 {
428 Reference< XDatabaseMetaData > xMeta( m_pImpl->xConnectionMetaData, UNO_SET_THROW );
429 OUString sConnectionURL( xMeta->getURL() );
430 bSupported = !sConnectionURL.startsWith( "sdbc:mysql:mysqlc" );
431 }
432 catch( const Exception& )
433 {
434 DBG_UNHANDLED_EXCEPTION("connectivity.commontools");
435 }
436 return bSupported;
437 }
438
439
440} // namespace dbtools
441
442
443/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
const css::uno::Any & get(const OUString &_rValueName) const
const ::comphelper::NamedValueCollection & getMetaData(std::u16string_view _sURL) const
helper class for accessing resources shared by different libraries in the connectivity module
OUString getResourceString(TranslateId pResId) const
loads a string from the shared resource file
encapsulates meta data about a database/connection which cannot be obtained from the usual XDatabaseM...
Definition: dbmetadata.hxx:50
bool supportsThreads() const
determines that threads are supported.
Definition: dbmetadata.cxx:423
DatabaseMetaData & operator=(const DatabaseMetaData &_copyFrom)
Definition: dbmetadata.cxx:190
sal_Int32 getBooleanComparisonMode() const
determines the syntax to use for boolean comparison predicates
Definition: dbmetadata.cxx:322
const OUString & getIdentifierQuoteString() const
wraps XDatabaseMetaData::getIdentifierQuoteString
Definition: dbmetadata.cxx:257
bool isAutoIncrementPrimaryKey() const
auto increment columns should be automatically used as primary key.
Definition: dbmetadata.cxx:312
bool restrictIdentifiersToSQL92() const
determines whether names in the database should be restricted to SQL-92 identifiers
Definition: dbmetadata.cxx:269
bool generateASBeforeCorrelationName() const
determines whether when generating SQL statements, an AS keyword should be generated before a correla...
Definition: dbmetadata.cxx:282
bool shouldSubstituteParameterNames() const
should named parameters (:foo, [foo]) be replaced by unnamed parameters (?)
Definition: dbmetadata.cxx:302
bool supportsPrimaryKeys() const
checks whether the database supports primary keys
Definition: dbmetadata.cxx:235
bool shouldEscapeDateTime() const
should date time be escaped like '2001-01-01' => {D '2001-01-01' }
Definition: dbmetadata.cxx:292
const OUString & getCatalogSeparator() const
wraps XDatabaseMetaData::getCatalogSeparator
Definition: dbmetadata.cxx:263
::std::unique_ptr< DatabaseMetaData_Impl > m_pImpl
Definition: dbmetadata.hxx:52
bool supportsColumnAliasInOrderBy() const
determines if column alias names can be used in the order by clause.
Definition: dbmetadata.cxx:360
bool supportsUserAdministration(const css::uno::Reference< css::uno::XComponentContext > &_rContext) const
determines whether user administration is supported for the database
Definition: dbmetadata.cxx:371
bool displayEmptyTableFolders() const
determines whether in the application UI, empty table folders (aka catalogs/schemas) should be displa...
Definition: dbmetadata.cxx:400
bool supportsRelations() const
determines in relations are supported.
Definition: dbmetadata.cxx:332
bool supportsSubqueriesInFrom() const
determines whether the database supports sub queries in the FROM part of a SELECT clause are supporte...
Definition: dbmetadata.cxx:215
bool isConnected() const
determines whether or not the instances is based on a valid connection
Definition: dbmetadata.cxx:209
#define DBG_UNHANDLED_EXCEPTION(...)
#define SAL_WARN(area, stream)
@ Exception
Reference< XComponentContext > getProcessComponentContext()
void throwSQLException(const OUString &_rMessage, const OUString &_rSQLState, const Reference< XInterface > &_rxContext, const sal_Int32 _nErrorCode)
ConversionMode mode
Reference< XConnection > xConnection
Definition: dbmetadata.cxx:70
Reference< XDatabaseMetaData > xConnectionMetaData
Definition: dbmetadata.cxx:71
::std::optional< OUString > sCachedIdentifierQuoteString
Definition: dbmetadata.cxx:74
::std::optional< OUString > sCachedCatalogSeparator
Definition: dbmetadata.cxx:75
::connectivity::DriversConfig aDriverConfig
Definition: dbmetadata.cxx:72