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 "resource/common_res.hrc"
37 #include "resource/sharedresources.hxx"
39 /** === begin UNO includes === **/
40 #include <com/sun/star/lang/IllegalArgumentException.hpp>
41 #include <com/sun/star/container/XChild.hpp>
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 #include <com/sun/star/beans/PropertyValue.hpp>
44 #include <com/sun/star/beans/XPropertySetInfo.hpp>
45 #include <com/sun/star/sdb/BooleanComparisonMode.hpp>
46 #include <com/sun/star/sdbc/XDatabaseMetaData2.hpp>
47 #include <com/sun/star/sdbcx/XUsersSupplier.hpp>
48 #include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp>
49 #include <com/sun/star/sdbc/XDriverAccess.hpp>
50 /** === end UNO includes === **/
52 #include <tools/diagnose_ex.h>
53 #include <comphelper/namedvaluecollection.hxx>
54 #include <comphelper/componentcontext.hxx>
56 #include <boost/optional.hpp>
58 //........................................................................
61 //........................................................................
63 /** === begin UNO using === **/
64 using ::com::sun::star::uno::Reference
;
65 using ::com::sun::star::sdbc::XConnection
;
66 using ::com::sun::star::sdbc::XConnection
;
67 using ::com::sun::star::sdbc::XDatabaseMetaData
;
68 using ::com::sun::star::sdbc::XDatabaseMetaData2
;
69 using ::com::sun::star::lang::IllegalArgumentException
;
70 using ::com::sun::star::uno::Exception
;
71 using ::com::sun::star::uno::Any
;
72 using ::com::sun::star::container::XChild
;
73 using ::com::sun::star::uno::UNO_QUERY_THROW
;
74 using ::com::sun::star::beans::XPropertySet
;
75 using ::com::sun::star::uno::Sequence
;
76 using ::com::sun::star::beans::PropertyValue
;
77 using ::com::sun::star::beans::XPropertySetInfo
;
78 using ::com::sun::star::uno::UNO_QUERY
;
79 using ::com::sun::star::sdbcx::XUsersSupplier
;
80 using ::com::sun::star::sdbcx::XDataDefinitionSupplier
;
81 using ::com::sun::star::sdbc::XDriverAccess
;
82 using ::com::sun::star::uno::UNO_SET_THROW
;
83 /** === end UNO using === **/
84 namespace BooleanComparisonMode
= ::com::sun::star::sdb::BooleanComparisonMode
;
86 //====================================================================
87 //= DatabaseMetaData_Impl
88 //====================================================================
89 struct DatabaseMetaData_Impl
91 Reference
< XConnection
> xConnection
;
92 Reference
< XDatabaseMetaData
> xConnectionMetaData
;
94 ::boost::optional
< ::rtl::OUString
> sCachedIdentifierQuoteString
;
95 ::boost::optional
< ::rtl::OUString
> sCachedCatalogSeparator
;
98 //--------------------------------------------------------------------
101 //................................................................
102 static void lcl_construct( DatabaseMetaData_Impl
& _metaDataImpl
, const Reference
< XConnection
>& _connection
)
104 _metaDataImpl
.xConnection
= _connection
;
105 if ( !_metaDataImpl
.xConnection
.is() )
108 _metaDataImpl
.xConnectionMetaData
= _connection
->getMetaData();
109 if ( !_metaDataImpl
.xConnectionMetaData
.is() )
110 throw IllegalArgumentException();
113 //................................................................
114 static void lcl_checkConnected( const DatabaseMetaData_Impl
& _metaDataImpl
)
116 if ( !_metaDataImpl
.xConnection
.is() || !_metaDataImpl
.xConnectionMetaData
.is() )
118 ::connectivity::SharedResources aResources
;
119 const ::rtl::OUString
sError( aResources
.getResourceString(STR_NO_CONNECTION_GIVEN
));
120 throwSQLException( sError
, SQL_CONNECTION_DOES_NOT_EXIST
, NULL
);
124 //................................................................
125 static bool lcl_getConnectionSetting( const sal_Char
* _asciiName
, const DatabaseMetaData_Impl
& _metaData
, Any
& _out_setting
)
129 Reference
< XChild
> xConnectionAsChild( _metaData
.xConnection
, UNO_QUERY
);
130 if ( xConnectionAsChild
.is() )
132 Reference
< XPropertySet
> xDataSource( xConnectionAsChild
->getParent(), UNO_QUERY_THROW
);
133 Reference
< XPropertySet
> xDataSourceSettings(
134 xDataSource
->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Settings" ) ) ),
137 _out_setting
= xDataSourceSettings
->getPropertyValue( ::rtl::OUString::createFromAscii( _asciiName
) );
141 Reference
< XDatabaseMetaData2
> xExtendedMetaData( _metaData
.xConnectionMetaData
, UNO_QUERY_THROW
);
142 ::comphelper::NamedValueCollection
aSettings( xExtendedMetaData
->getConnectionInfo() );
143 _out_setting
= aSettings
.get( _asciiName
);
144 return _out_setting
.hasValue();
148 catch( const Exception
& )
150 DBG_UNHANDLED_EXCEPTION();
155 //................................................................
156 static const ::rtl::OUString
& lcl_getConnectionStringSetting(
157 const DatabaseMetaData_Impl
& _metaData
, ::boost::optional
< ::rtl::OUString
>& _cachedSetting
,
158 ::rtl::OUString (SAL_CALL
XDatabaseMetaData::*_getter
)() )
160 if ( !_cachedSetting
)
162 lcl_checkConnected( _metaData
);
165 _cachedSetting
.reset( (_metaData
.xConnectionMetaData
.get()->*_getter
)() );
167 catch( const Exception
& ) { DBG_UNHANDLED_EXCEPTION(); }
169 return *_cachedSetting
;
173 //====================================================================
175 //====================================================================
176 //--------------------------------------------------------------------
177 DatabaseMetaData::DatabaseMetaData()
178 :m_pImpl( new DatabaseMetaData_Impl
)
182 //--------------------------------------------------------------------
183 DatabaseMetaData::DatabaseMetaData( const Reference
< XConnection
>& _connection
)
184 :m_pImpl( new DatabaseMetaData_Impl
)
186 lcl_construct( *m_pImpl
, _connection
);
189 //--------------------------------------------------------------------
190 DatabaseMetaData::DatabaseMetaData( const DatabaseMetaData
& _copyFrom
)
191 :m_pImpl( new DatabaseMetaData_Impl( *_copyFrom
.m_pImpl
) )
195 //--------------------------------------------------------------------
196 DatabaseMetaData
& DatabaseMetaData::operator=( const DatabaseMetaData
& _copyFrom
)
198 if ( this == &_copyFrom
)
201 m_pImpl
.reset( new DatabaseMetaData_Impl( *_copyFrom
.m_pImpl
) );
205 //--------------------------------------------------------------------
206 DatabaseMetaData::~DatabaseMetaData()
210 //--------------------------------------------------------------------
211 bool DatabaseMetaData::isConnected() const
213 return m_pImpl
->xConnection
.is();
216 //--------------------------------------------------------------------
217 bool DatabaseMetaData::supportsSubqueriesInFrom() const
219 lcl_checkConnected( *m_pImpl
);
221 bool supportsSubQueries
= false;
224 sal_Int32 maxTablesInselect
= m_pImpl
->xConnectionMetaData
->getMaxTablesInSelect();
225 supportsSubQueries
= ( maxTablesInselect
> 1 ) || ( maxTablesInselect
== 0 );
226 // TODO: is there a better way to determine this? The above is not really true. More precise,
227 // it's a *very* generous heuristics ...
229 catch( const Exception
& )
231 DBG_UNHANDLED_EXCEPTION();
233 return supportsSubQueries
;
236 //--------------------------------------------------------------------
237 const ::rtl::OUString
& DatabaseMetaData::getIdentifierQuoteString() const
239 return lcl_getConnectionStringSetting( *m_pImpl
, m_pImpl
->sCachedIdentifierQuoteString
, &XDatabaseMetaData::getIdentifierQuoteString
);
242 //--------------------------------------------------------------------
243 const ::rtl::OUString
& DatabaseMetaData::getCatalogSeparator() const
245 return lcl_getConnectionStringSetting( *m_pImpl
, m_pImpl
->sCachedCatalogSeparator
, &XDatabaseMetaData::getCatalogSeparator
);
248 //--------------------------------------------------------------------
249 bool DatabaseMetaData::restrictIdentifiersToSQL92() const
251 lcl_checkConnected( *m_pImpl
);
253 bool restrict( false );
255 if ( lcl_getConnectionSetting( "EnableSQL92Check", *m_pImpl
, setting
) )
256 OSL_VERIFY( setting
>>= restrict
);
260 //--------------------------------------------------------------------
261 bool DatabaseMetaData::generateASBeforeCorrelationName() const
263 bool doGenerate( true );
265 if ( lcl_getConnectionSetting( "GenerateASBeforeCorrelationName", *m_pImpl
, setting
) )
266 OSL_VERIFY( setting
>>= doGenerate
);
269 //--------------------------------------------------------------------
270 bool DatabaseMetaData::shouldEscapeDateTime() const
272 bool doGenerate( true );
274 if ( lcl_getConnectionSetting( "EscapeDateTime", *m_pImpl
, setting
) )
275 OSL_VERIFY( setting
>>= doGenerate
);
278 //--------------------------------------------------------------------
279 bool DatabaseMetaData::isAutoIncrementPrimaryKey() const
281 bool doGenerate( true );
283 if ( lcl_getConnectionSetting( "AutoIncrementIsPrimaryKey", *m_pImpl
, setting
) )
284 OSL_VERIFY( setting
>>= doGenerate
);
287 //--------------------------------------------------------------------
288 sal_Int32
DatabaseMetaData::getBooleanComparisonMode() const
290 sal_Int32
mode( BooleanComparisonMode::EQUAL_INTEGER
);
292 if ( lcl_getConnectionSetting( "BooleanComparisonMode", *m_pImpl
, setting
) )
293 OSL_VERIFY( setting
>>= mode
);
296 //--------------------------------------------------------------------
297 bool DatabaseMetaData::supportsRelations() const
299 lcl_checkConnected( *m_pImpl
);
300 bool bSupport
= false;
303 bSupport
= m_pImpl
->xConnectionMetaData
->supportsIntegrityEnhancementFacility();
305 catch( const Exception
& )
307 DBG_UNHANDLED_EXCEPTION();
313 const ::rtl::OUString url
= m_pImpl
->xConnectionMetaData
->getURL();
314 char pMySQL
[] = "sdbc:mysql";
315 bSupport
= url
.matchAsciiL(pMySQL
,(sizeof(pMySQL
)/sizeof(pMySQL
[0]))-1);
318 catch( const Exception
& )
320 DBG_UNHANDLED_EXCEPTION();
325 //--------------------------------------------------------------------
326 bool DatabaseMetaData::supportsColumnAliasInOrderBy() const
328 bool doGenerate( true );
330 if ( lcl_getConnectionSetting( "ColumnAliasInOrderBy", *m_pImpl
, setting
) )
331 OSL_VERIFY( setting
>>= doGenerate
);
335 //--------------------------------------------------------------------
336 bool DatabaseMetaData::supportsUserAdministration( const ::comphelper::ComponentContext
& _rContext
) const
338 lcl_checkConnected( *m_pImpl
);
340 bool isSupported( false );
343 // find the XUsersSupplier interface
344 // - either directly at the connection
345 Reference
< XUsersSupplier
> xUsersSupp( m_pImpl
->xConnection
, UNO_QUERY
);
346 if ( !xUsersSupp
.is() )
348 // - or at the driver manager
349 Reference
< XDriverAccess
> xDriverManager(
350 _rContext
.createComponent( "com.sun.star.sdbc.DriverManager" ), UNO_QUERY_THROW
);
351 Reference
< XDataDefinitionSupplier
> xDriver( xDriverManager
->getDriverByURL( m_pImpl
->xConnectionMetaData
->getURL() ), UNO_QUERY
);
353 xUsersSupp
.set( xDriver
->getDataDefinitionByConnection( m_pImpl
->xConnection
), UNO_QUERY
);
356 isSupported
= ( xUsersSupp
.is() && xUsersSupp
->getUsers().is() );
358 catch( const Exception
& )
360 DBG_UNHANDLED_EXCEPTION();
365 //--------------------------------------------------------------------
366 bool DatabaseMetaData::displayEmptyTableFolders() const
368 bool doDisplay( true );
369 #ifdef IMPLEMENTED_LATER
371 if ( lcl_getConnectionSetting( "DisplayEmptyTableFolders", *m_pImpl
, setting
) )
372 OSL_VERIFY( setting
>>= doDisplay
);
376 Reference
< XDatabaseMetaData
> xMeta( m_pImpl
->xConnectionMetaData
, UNO_SET_THROW
);
377 ::rtl::OUString
sConnectionURL( xMeta
->getURL() );
378 doDisplay
= sConnectionURL
.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "sdbc:mysql:mysqlc" ) ) == 0;
380 catch( const Exception
& )
382 DBG_UNHANDLED_EXCEPTION();
388 //........................................................................
389 } // namespace dbtools
390 //........................................................................