1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dbmetadata.cxx,v $
10 * $Revision: 1.10.22.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
34 #include "connectivity/dbmetadata.hxx"
35 #include "connectivity/dbexception.hxx"
36 #include "connectivity/DriversConfig.hxx"
37 #include "resource/common_res.hrc"
38 #include "resource/sharedresources.hxx"
40 /** === begin UNO includes === **/
41 #include <com/sun/star/lang/IllegalArgumentException.hpp>
42 #include <com/sun/star/container/XChild.hpp>
43 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <com/sun/star/beans/PropertyValue.hpp>
45 #include <com/sun/star/beans/XPropertySetInfo.hpp>
46 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
47 #include <com/sun/star/sdbc/XDatabaseMetaData2.hpp>
48 #include <com/sun/star/sdbcx/XUsersSupplier.hpp>
49 #include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp>
50 #include <com/sun/star/sdbc/XDriverAccess.hpp>
51 /** === end UNO includes === **/
53 #include <tools/diagnose_ex.h>
54 #include <comphelper/namedvaluecollection.hxx>
55 #include <comphelper/componentcontext.hxx>
56 #include <comphelper/processfactory.hxx>
58 #include <boost/optional.hpp>
60 //........................................................................
63 //........................................................................
65 /** === begin UNO using === **/
66 using ::com::sun::star::uno::Reference
;
67 using ::com::sun::star::sdbc::XConnection
;
68 using ::com::sun::star::sdbc::XConnection
;
69 using ::com::sun::star::sdbc::XDatabaseMetaData
;
70 using ::com::sun::star::sdbc::XDatabaseMetaData2
;
71 using ::com::sun::star::lang::IllegalArgumentException
;
72 using ::com::sun::star::uno::Exception
;
73 using ::com::sun::star::uno::Any
;
74 using ::com::sun::star::container::XChild
;
75 using ::com::sun::star::uno::UNO_QUERY_THROW
;
76 using ::com::sun::star::beans::XPropertySet
;
77 using ::com::sun::star::uno::Sequence
;
78 using ::com::sun::star::beans::PropertyValue
;
79 using ::com::sun::star::beans::XPropertySetInfo
;
80 using ::com::sun::star::uno::UNO_QUERY
;
81 using ::com::sun::star::sdbcx::XUsersSupplier
;
82 using ::com::sun::star::sdbcx::XDataDefinitionSupplier
;
83 using ::com::sun::star::sdbc::XDriverAccess
;
84 using ::com::sun::star::uno::UNO_SET_THROW
;
85 /** === end UNO using === **/
86 namespace BooleanComparisonMode
= ::com::sun::star::sdb::BooleanComparisonMode
;
88 //====================================================================
89 //= DatabaseMetaData_Impl
90 //====================================================================
91 struct DatabaseMetaData_Impl
93 Reference
< XConnection
> xConnection
;
94 Reference
< XDatabaseMetaData
> xConnectionMetaData
;
95 ::connectivity::DriversConfig aDriverConfig
;
97 ::boost::optional
< ::rtl::OUString
> sCachedIdentifierQuoteString
;
98 ::boost::optional
< ::rtl::OUString
> sCachedCatalogSeparator
;
100 DatabaseMetaData_Impl()
102 ,xConnectionMetaData()
103 ,aDriverConfig( ::comphelper::getProcessServiceFactory() )
104 ,sCachedIdentifierQuoteString()
105 ,sCachedCatalogSeparator()
110 //--------------------------------------------------------------------
113 //................................................................
114 static void lcl_construct( DatabaseMetaData_Impl
& _metaDataImpl
, const Reference
< XConnection
>& _connection
)
116 _metaDataImpl
.xConnection
= _connection
;
117 if ( !_metaDataImpl
.xConnection
.is() )
120 _metaDataImpl
.xConnectionMetaData
= _connection
->getMetaData();
121 if ( !_metaDataImpl
.xConnectionMetaData
.is() )
122 throw IllegalArgumentException();
125 //................................................................
126 static void lcl_checkConnected( const DatabaseMetaData_Impl
& _metaDataImpl
)
128 if ( !_metaDataImpl
.xConnection
.is() || !_metaDataImpl
.xConnectionMetaData
.is() )
130 ::connectivity::SharedResources aResources
;
131 const ::rtl::OUString
sError( aResources
.getResourceString(STR_NO_CONNECTION_GIVEN
));
132 throwSQLException( sError
, SQL_CONNECTION_DOES_NOT_EXIST
, NULL
);
136 //................................................................
137 static bool lcl_getDriverSetting( const sal_Char
* _asciiName
, const DatabaseMetaData_Impl
& _metaData
, Any
& _out_setting
)
139 lcl_checkConnected( _metaData
);
140 const ::comphelper::NamedValueCollection
& rDriverMetaData
= _metaData
.aDriverConfig
.getMetaData( _metaData
.xConnectionMetaData
->getURL() );
141 if ( !rDriverMetaData
.has( _asciiName
) )
143 _out_setting
= rDriverMetaData
.get( _asciiName
);
147 //................................................................
148 static bool lcl_getConnectionSetting( const sal_Char
* _asciiName
, const DatabaseMetaData_Impl
& _metaData
, Any
& _out_setting
)
152 Reference
< XChild
> xConnectionAsChild( _metaData
.xConnection
, UNO_QUERY
);
153 if ( xConnectionAsChild
.is() )
155 Reference
< XPropertySet
> xDataSource( xConnectionAsChild
->getParent(), UNO_QUERY_THROW
);
156 Reference
< XPropertySet
> xDataSourceSettings(
157 xDataSource
->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Settings" ) ) ),
160 _out_setting
= xDataSourceSettings
->getPropertyValue( ::rtl::OUString::createFromAscii( _asciiName
) );
164 Reference
< XDatabaseMetaData2
> xExtendedMetaData( _metaData
.xConnectionMetaData
, UNO_QUERY_THROW
);
165 ::comphelper::NamedValueCollection
aSettings( xExtendedMetaData
->getConnectionInfo() );
166 _out_setting
= aSettings
.get( _asciiName
);
167 return _out_setting
.hasValue();
171 catch( const Exception
& )
173 DBG_UNHANDLED_EXCEPTION();
178 //................................................................
179 static const ::rtl::OUString
& lcl_getConnectionStringSetting(
180 const DatabaseMetaData_Impl
& _metaData
, ::boost::optional
< ::rtl::OUString
>& _cachedSetting
,
181 ::rtl::OUString (SAL_CALL
XDatabaseMetaData::*_getter
)() )
183 if ( !_cachedSetting
)
185 lcl_checkConnected( _metaData
);
188 _cachedSetting
.reset( (_metaData
.xConnectionMetaData
.get()->*_getter
)() );
190 catch( const Exception
& ) { DBG_UNHANDLED_EXCEPTION(); }
192 return *_cachedSetting
;
196 //====================================================================
198 //====================================================================
199 //--------------------------------------------------------------------
200 DatabaseMetaData::DatabaseMetaData()
201 :m_pImpl( new DatabaseMetaData_Impl
)
205 //--------------------------------------------------------------------
206 DatabaseMetaData::DatabaseMetaData( const Reference
< XConnection
>& _connection
)
207 :m_pImpl( new DatabaseMetaData_Impl
)
209 lcl_construct( *m_pImpl
, _connection
);
212 //--------------------------------------------------------------------
213 DatabaseMetaData::DatabaseMetaData( const DatabaseMetaData
& _copyFrom
)
214 :m_pImpl( new DatabaseMetaData_Impl( *_copyFrom
.m_pImpl
) )
218 //--------------------------------------------------------------------
219 DatabaseMetaData
& DatabaseMetaData::operator=( const DatabaseMetaData
& _copyFrom
)
221 if ( this == &_copyFrom
)
224 m_pImpl
.reset( new DatabaseMetaData_Impl( *_copyFrom
.m_pImpl
) );
228 //--------------------------------------------------------------------
229 DatabaseMetaData::~DatabaseMetaData()
233 //--------------------------------------------------------------------
234 bool DatabaseMetaData::isConnected() const
236 return m_pImpl
->xConnection
.is();
239 //--------------------------------------------------------------------
240 bool DatabaseMetaData::supportsSubqueriesInFrom() const
242 lcl_checkConnected( *m_pImpl
);
244 bool supportsSubQueries
= false;
247 sal_Int32 maxTablesInselect
= m_pImpl
->xConnectionMetaData
->getMaxTablesInSelect();
248 supportsSubQueries
= ( maxTablesInselect
> 1 ) || ( maxTablesInselect
== 0 );
249 // TODO: is there a better way to determine this? The above is not really true. More precise,
250 // it's a *very* generous heuristics ...
252 catch( const Exception
& )
254 DBG_UNHANDLED_EXCEPTION();
256 return supportsSubQueries
;
259 //--------------------------------------------------------------------
260 const ::rtl::OUString
& DatabaseMetaData::getIdentifierQuoteString() const
262 return lcl_getConnectionStringSetting( *m_pImpl
, m_pImpl
->sCachedIdentifierQuoteString
, &XDatabaseMetaData::getIdentifierQuoteString
);
265 //--------------------------------------------------------------------
266 const ::rtl::OUString
& DatabaseMetaData::getCatalogSeparator() const
268 return lcl_getConnectionStringSetting( *m_pImpl
, m_pImpl
->sCachedCatalogSeparator
, &XDatabaseMetaData::getCatalogSeparator
);
271 //--------------------------------------------------------------------
272 bool DatabaseMetaData::restrictIdentifiersToSQL92() const
274 lcl_checkConnected( *m_pImpl
);
276 bool restrict( false );
278 if ( lcl_getConnectionSetting( "EnableSQL92Check", *m_pImpl
, setting
) )
279 OSL_VERIFY( setting
>>= restrict
);
283 //--------------------------------------------------------------------
284 bool DatabaseMetaData::generateASBeforeCorrelationName() const
286 bool doGenerate( true );
288 if ( lcl_getConnectionSetting( "GenerateASBeforeCorrelationName", *m_pImpl
, setting
) )
289 OSL_VERIFY( setting
>>= doGenerate
);
292 //--------------------------------------------------------------------
293 bool DatabaseMetaData::shouldEscapeDateTime() const
295 bool doGenerate( true );
297 if ( lcl_getConnectionSetting( "EscapeDateTime", *m_pImpl
, setting
) )
298 OSL_VERIFY( setting
>>= doGenerate
);
301 //--------------------------------------------------------------------
302 bool DatabaseMetaData::isAutoIncrementPrimaryKey() const
306 if ( lcl_getDriverSetting( "AutoIncrementIsPrimaryKey", *m_pImpl
, setting
) )
307 OSL_VERIFY( setting
>>= is
);
310 //--------------------------------------------------------------------
311 sal_Int32
DatabaseMetaData::getBooleanComparisonMode() const
313 sal_Int32
mode( BooleanComparisonMode::EQUAL_INTEGER
);
315 if ( lcl_getConnectionSetting( "BooleanComparisonMode", *m_pImpl
, setting
) )
316 OSL_VERIFY( setting
>>= mode
);
319 //--------------------------------------------------------------------
320 bool DatabaseMetaData::supportsRelations() const
322 lcl_checkConnected( *m_pImpl
);
323 bool bSupport
= false;
326 bSupport
= m_pImpl
->xConnectionMetaData
->supportsIntegrityEnhancementFacility();
328 catch( const Exception
& )
330 DBG_UNHANDLED_EXCEPTION();
336 const ::rtl::OUString url
= m_pImpl
->xConnectionMetaData
->getURL();
337 char pMySQL
[] = "sdbc:mysql";
338 bSupport
= url
.matchAsciiL(pMySQL
,(sizeof(pMySQL
)/sizeof(pMySQL
[0]))-1);
341 catch( const Exception
& )
343 DBG_UNHANDLED_EXCEPTION();
348 //--------------------------------------------------------------------
349 bool DatabaseMetaData::supportsColumnAliasInOrderBy() const
351 bool doGenerate( true );
353 if ( lcl_getConnectionSetting( "ColumnAliasInOrderBy", *m_pImpl
, setting
) )
354 OSL_VERIFY( setting
>>= doGenerate
);
358 //--------------------------------------------------------------------
359 bool DatabaseMetaData::supportsUserAdministration( const ::comphelper::ComponentContext
& _rContext
) const
361 lcl_checkConnected( *m_pImpl
);
363 bool isSupported( false );
366 // find the XUsersSupplier interface
367 // - either directly at the connection
368 Reference
< XUsersSupplier
> xUsersSupp( m_pImpl
->xConnection
, UNO_QUERY
);
369 if ( !xUsersSupp
.is() )
371 // - or at the driver manager
372 Reference
< XDriverAccess
> xDriverManager(
373 _rContext
.createComponent( "com.sun.star.sdbc.DriverManager" ), UNO_QUERY_THROW
);
374 Reference
< XDataDefinitionSupplier
> xDriver( xDriverManager
->getDriverByURL( m_pImpl
->xConnectionMetaData
->getURL() ), UNO_QUERY
);
376 xUsersSupp
.set( xDriver
->getDataDefinitionByConnection( m_pImpl
->xConnection
), UNO_QUERY
);
379 isSupported
= ( xUsersSupp
.is() && xUsersSupp
->getUsers().is() );
381 catch( const Exception
& )
383 DBG_UNHANDLED_EXCEPTION();
388 //--------------------------------------------------------------------
389 bool DatabaseMetaData::displayEmptyTableFolders() const
391 bool doDisplay( true );
392 #ifdef IMPLEMENTED_LATER
394 if ( lcl_getConnectionSetting( "DisplayEmptyTableFolders", *m_pImpl
, setting
) )
395 OSL_VERIFY( setting
>>= doDisplay
);
399 Reference
< XDatabaseMetaData
> xMeta( m_pImpl
->xConnectionMetaData
, UNO_SET_THROW
);
400 ::rtl::OUString
sConnectionURL( xMeta
->getURL() );
401 doDisplay
= sConnectionURL
.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:mysqlc" ) ) == 0;
403 catch( const Exception
& )
405 DBG_UNHANDLED_EXCEPTION();
411 //........................................................................
412 } // namespace dbtools
413 //........................................................................