LCOV - code coverage report
Current view: top level - libreoffice/connectivity/source/commontools - dbmetadata.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 25 157 15.9 %
Date: 2012-12-27 Functions: 7 28 25.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10