LCOV - code coverage report
Current view: top level - dbaccess/source/core/api - FilteredContainer.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 53 197 26.9 %
Date: 2014-04-11 Functions: 9 18 50.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             : #include "dbastrings.hrc"
      21             : #include "FilteredContainer.hxx"
      22             : #include "RefreshListener.hxx"
      23             : #include "sdbcoretools.hxx"
      24             : #include <com/sun/star/sdbc/XRow.hpp>
      25             : #include <connectivity/dbtools.hxx>
      26             : #include <tools/wldcrd.hxx>
      27             : #include <tools/diagnose_ex.h>
      28             : #include <boost/optional.hpp>
      29             : 
      30             : namespace dbaccess
      31             : {
      32             :     using namespace dbtools;
      33             :     using namespace ::com::sun::star::uno;
      34             :     using namespace ::com::sun::star::lang;
      35             :     using namespace ::com::sun::star::beans;
      36             :     using namespace ::com::sun::star::sdbc;
      37             :     using namespace ::com::sun::star::sdb;
      38             :     using namespace ::com::sun::star::sdbcx;
      39             :     using namespace ::com::sun::star::util;
      40             :     using namespace ::com::sun::star::container;
      41             :     using namespace ::osl;
      42             :     using namespace ::comphelper;
      43             :     using namespace ::cppu;
      44             :     using namespace ::connectivity::sdbcx;
      45             : 
      46             : /** creates a vector of WildCards and reduce the _rTableFilter of the length of WildsCards
      47             : */
      48           0 : sal_Int32 createWildCardVector(Sequence< OUString >& _rTableFilter, ::std::vector< WildCard >& _rOut)
      49             : {
      50             :     SAL_INFO("dbaccess", "api OFilteredContainer::createWildCardVector" );
      51             :     // for wildcard search : remove all table filters which are a wildcard expression and build a WilCard
      52             :     // for them
      53           0 :     OUString* pTableFilters = _rTableFilter.getArray();
      54           0 :     OUString* pEnd          = pTableFilters + _rTableFilter.getLength();
      55           0 :     sal_Int32 nShiftPos = 0;
      56           0 :     for (sal_Int32 i=0; pEnd != pTableFilters; ++pTableFilters,++i)
      57             :     {
      58           0 :         if (pTableFilters->indexOf('%') != -1)
      59             :         {
      60           0 :             _rOut.push_back(WildCard(pTableFilters->replace('%', '*')));
      61             :         }
      62             :         else
      63             :         {
      64           0 :             if (nShiftPos != i)
      65             :             {
      66           0 :                 _rTableFilter.getArray()[nShiftPos] = _rTableFilter.getArray()[i];
      67             :             }
      68           0 :             ++nShiftPos;
      69             :         }
      70             :     }
      71             :     // now aTableFilter contains nShiftPos non-wc-strings and aWCSearch all wc-strings
      72           0 :     _rTableFilter.realloc(nShiftPos);
      73           0 :     return nShiftPos;
      74             : }
      75             : 
      76           0 :     bool lcl_isElementAllowed(  const OUString& _rName,
      77             :                                 const Sequence< OUString >& _rTableFilter,
      78             :                                 const ::std::vector< WildCard >& _rWCSearch )
      79             :     {
      80           0 :         sal_Int32 nTableFilterLen = _rTableFilter.getLength();
      81             : 
      82           0 :         const OUString* tableFilter = _rTableFilter.getConstArray();
      83           0 :         const OUString* tableFilterEnd = _rTableFilter.getConstArray() + nTableFilterLen;
      84           0 :         bool bFilterMatch = ::std::find( tableFilter, tableFilterEnd, _rName ) != tableFilterEnd;
      85             :         // the table is allowed to "pass" if we had no filters at all or any of the non-wildcard filters matches
      86           0 :         if (!bFilterMatch && !_rWCSearch.empty())
      87             :         {   // or if one of the wildcrad expression matches
      88           0 :             for (   ::std::vector< WildCard >::const_iterator aLoop = _rWCSearch.begin();
      89           0 :                     aLoop != _rWCSearch.end() && !bFilterMatch;
      90             :                     ++aLoop
      91             :                 )
      92           0 :                 bFilterMatch = aLoop->Matches( _rName );
      93             :         }
      94             : 
      95           0 :         return bFilterMatch;
      96             :     }
      97             : 
      98             :     typedef ::boost::optional< OUString >    OptionalString;
      99         345 :     struct TableInfo
     100             :     {
     101             :         OptionalString  sComposedName;
     102             :         OptionalString  sType;
     103             :         OptionalString  sCatalog;
     104             :         OptionalString  sSchema;
     105             :         OptionalString  sName;
     106             : 
     107          55 :         TableInfo( const OUString& _composedName )
     108          55 :             :sComposedName( _composedName )
     109             :         {
     110          55 :         }
     111             : 
     112           0 :         TableInfo( const OUString& _catalog, const OUString& _schema, const OUString& _name,
     113             :             const OUString& _type )
     114             :             :sComposedName()
     115             :             ,sType( _type )
     116             :             ,sCatalog( _catalog )
     117             :             ,sSchema( _schema )
     118           0 :             ,sName( _name )
     119             :         {
     120           0 :         }
     121             :     };
     122             :     typedef ::std::vector< TableInfo >    TableInfos;
     123             : 
     124          55 :     void lcl_ensureComposedName( TableInfo& _io_tableInfo, const Reference< XDatabaseMetaData >& _metaData )
     125             :     {
     126          55 :         if ( !_metaData.is() )
     127           0 :             throw RuntimeException();
     128             : 
     129          55 :         if ( !_io_tableInfo.sComposedName )
     130             :         {
     131             :             OSL_ENSURE( !!_io_tableInfo.sCatalog && !!_io_tableInfo.sSchema && !!_io_tableInfo.sName, "lcl_ensureComposedName: How should I composed the name from nothing!?" );
     132             : 
     133           0 :             _io_tableInfo.sComposedName = OptionalString(
     134           0 :                 composeTableName( _metaData, *_io_tableInfo.sCatalog, *_io_tableInfo.sSchema, *_io_tableInfo.sName,
     135             :                 false, ::dbtools::eInDataManipulation )
     136           0 :             );
     137             :         }
     138          55 :     }
     139             : 
     140           0 :     void lcl_ensureType( TableInfo& _io_tableInfo, const Reference< XDatabaseMetaData >& _metaData, const Reference< XNameAccess >& _masterContainer )
     141             :     {
     142           0 :         if ( !!_io_tableInfo.sType )
     143           0 :             return;
     144             : 
     145           0 :         lcl_ensureComposedName( _io_tableInfo, _metaData );
     146             : 
     147           0 :         if ( !_masterContainer.is() )
     148           0 :             throw RuntimeException();
     149             : 
     150           0 :         OUString sTypeName;
     151             :         try
     152             :         {
     153           0 :             Reference< XPropertySet > xTable( _masterContainer->getByName( *_io_tableInfo.sComposedName ), UNO_QUERY_THROW );
     154           0 :             OSL_VERIFY( xTable->getPropertyValue( PROPERTY_TYPE ) >>= sTypeName );
     155             :         }
     156           0 :         catch( const Exception& )
     157             :         {
     158             :             DBG_UNHANDLED_EXCEPTION();
     159             :         }
     160           0 :         _io_tableInfo.sType = OptionalString( sTypeName );
     161             :     }
     162             : 
     163          29 :     connectivity::TStringVector lcl_filter( const TableInfos& _unfilteredTables,
     164             :         const Sequence< OUString >& _tableFilter, const Sequence< OUString >& _tableTypeFilter,
     165             :         const Reference< XDatabaseMetaData >& _metaData, const Reference< XNameAccess >& _masterContainer )
     166             :     {
     167          29 :         TableInfos aFilteredTables;
     168             : 
     169             :         // first, filter for the table names
     170          29 :         sal_Int32 nTableFilterCount = _tableFilter.getLength();
     171          29 :         sal_Bool dontFilterTableNames = ( ( nTableFilterCount == 1 ) && _tableFilter[0] == "%" );
     172          29 :         if( dontFilterTableNames )
     173             :         {
     174          29 :             aFilteredTables = _unfilteredTables;
     175             :         }
     176             :         else
     177             :         {
     178             :             // for wildcard search : remove all table filters which are a wildcard expression and build a WildCard
     179             :             // for them
     180           0 :             ::std::vector< WildCard > aWildCardTableFilter;
     181           0 :             Sequence< OUString > aNonWildCardTableFilter = _tableFilter;
     182           0 :             nTableFilterCount = createWildCardVector( aNonWildCardTableFilter, aWildCardTableFilter );
     183             : 
     184           0 :             TableInfos aUnfilteredTables( _unfilteredTables );
     185           0 :             aUnfilteredTables.reserve( nTableFilterCount + ( aWildCardTableFilter.size() * 10 ) );
     186             : 
     187           0 :             for (   TableInfos::iterator table = aUnfilteredTables.begin();
     188           0 :                     table != aUnfilteredTables.end();
     189             :                     ++table
     190             :                 )
     191             :             {
     192           0 :                 lcl_ensureComposedName( *table, _metaData );
     193             : 
     194           0 :                 if ( lcl_isElementAllowed( *table->sComposedName, aNonWildCardTableFilter, aWildCardTableFilter ) )
     195           0 :                     aFilteredTables.push_back( *table );
     196           0 :             }
     197             :         }
     198             : 
     199             :         // second, filter for the table types
     200          29 :         sal_Int32 nTableTypeFilterCount = _tableTypeFilter.getLength();
     201          29 :         sal_Bool dontFilterTableTypes = ( ( nTableTypeFilterCount == 1 ) && _tableTypeFilter[0] == "%" );
     202          29 :         dontFilterTableTypes = dontFilterTableTypes || ( nTableTypeFilterCount == 0 );
     203             :             // (for TableTypeFilter, unlike TableFilter, "empty" means "do not filter at all")
     204          29 :         if ( !dontFilterTableTypes )
     205             :         {
     206           0 :             TableInfos aUnfilteredTables;
     207           0 :             aUnfilteredTables.swap( aFilteredTables );
     208             : 
     209           0 :             const OUString* pTableTypeFilterBegin = _tableTypeFilter.getConstArray();
     210           0 :             const OUString* pTableTypeFilterEnd = pTableTypeFilterBegin + _tableTypeFilter.getLength();
     211             : 
     212           0 :             for (   TableInfos::iterator table = aUnfilteredTables.begin();
     213           0 :                     table != aUnfilteredTables.end();
     214             :                     ++table
     215             :                 )
     216             :             {
     217             :                 // ensure that we know the table type
     218           0 :                 lcl_ensureType( *table, _metaData, _masterContainer );
     219             : 
     220           0 :                 if ( ::std::find( pTableTypeFilterBegin, pTableTypeFilterEnd, *table->sType ) != pTableTypeFilterEnd )
     221           0 :                     aFilteredTables.push_back( *table );
     222           0 :             }
     223             :         }
     224             : 
     225          29 :         connectivity::TStringVector aReturn;
     226         252 :         for (   TableInfos::iterator table = aFilteredTables.begin();
     227         168 :                 table != aFilteredTables.end();
     228             :                 ++table
     229             :             )
     230             :         {
     231          55 :             lcl_ensureComposedName( *table, _metaData );
     232          55 :             aReturn.push_back( *table->sComposedName );
     233             :         }
     234          29 :         return aReturn;
     235             :     }
     236             : 
     237             :     // OViewContainer
     238          33 :     OFilteredContainer::OFilteredContainer(::cppu::OWeakObject& _rParent,
     239             :                                  ::osl::Mutex& _rMutex,
     240             :                                  const Reference< XConnection >& _xCon,
     241             :                                  sal_Bool _bCase,
     242             :                                  IRefreshListener*  _pRefreshListener,
     243             :                                  ::dbtools::IWarningsContainer* _pWarningsContainer
     244             :                                  ,oslInterlockedCount& _nInAppend)
     245             :         :OCollection(_rParent,_bCase,_rMutex,::std::vector< OUString>())
     246             :         ,m_bConstructed(sal_False)
     247             :         ,m_pWarningsContainer(_pWarningsContainer)
     248             :         ,m_pRefreshListener(_pRefreshListener)
     249             :         ,m_nInAppend(_nInAppend)
     250          33 :         ,m_xConnection(_xCon)
     251             :     {
     252          33 :     }
     253             : 
     254          29 :     void OFilteredContainer::construct(const Reference< XNameAccess >& _rxMasterContainer,
     255             :                                     const Sequence< OUString >& _rTableFilter,
     256             :                                     const Sequence< OUString >& _rTableTypeFilter)
     257             :     {
     258             :         try
     259             :         {
     260          29 :             Reference<XConnection> xCon = m_xConnection;
     261          29 :             if ( xCon.is() )
     262          29 :                 m_xMetaData = xCon->getMetaData();
     263             :         }
     264           0 :         catch(SQLException&)
     265             :         {
     266             :             DBG_UNHANDLED_EXCEPTION();
     267             :         }
     268             : 
     269          29 :         m_xMasterContainer = _rxMasterContainer;
     270             : 
     271          29 :         if ( m_xMasterContainer.is() )
     272             :         {
     273          29 :             addMasterContainerListener();
     274             : 
     275          29 :             TableInfos aUnfilteredTables;
     276             : 
     277          58 :             Sequence< OUString > aNames = m_xMasterContainer->getElementNames();
     278          29 :             const OUString*  name = aNames.getConstArray();
     279          29 :             const OUString*  nameEnd = name + aNames.getLength();
     280          84 :             for ( ; name != nameEnd; ++name )
     281          55 :                 aUnfilteredTables.push_back( TableInfo( *name ) );
     282             : 
     283             :             reFill( lcl_filter( aUnfilteredTables,
     284          29 :                 _rTableFilter, _rTableTypeFilter, m_xMetaData, m_xMasterContainer ) );
     285             : 
     286          58 :             m_bConstructed = sal_True;
     287             :         }
     288             :         else
     289             :         {
     290           0 :             construct( _rTableFilter, _rTableTypeFilter );
     291             :         }
     292          29 :     }
     293             : 
     294           0 :     void OFilteredContainer::construct(const Sequence< OUString >& _rTableFilter, const Sequence< OUString >& _rTableTypeFilter)
     295             :     {
     296             :         // build sorted versions of the filter sequences, so the visibility decision is faster
     297           0 :         Sequence< OUString > aTableFilter(_rTableFilter);
     298             : 
     299             :         // for wildcard search : remove all table filters which are a wildcard expression and build a WildCard
     300             :         // for them
     301           0 :         ::std::vector< WildCard > aWCSearch;
     302           0 :         createWildCardVector(aTableFilter,aWCSearch);
     303             : 
     304             :         try
     305             :         {
     306           0 :             SAL_DEBUG("OFilteredContainer::construct(). "
     307             :                       "Getting metadata ...");
     308             : 
     309           0 :             Reference< XConnection > xCon( m_xConnection, UNO_SET_THROW );
     310           0 :             m_xMetaData.set( xCon->getMetaData(), UNO_SET_THROW );
     311             : 
     312           0 :             SAL_DEBUG("OFilteredContainer::construct(). "
     313             :                       "Metadata got.");
     314             : 
     315             :             // create a table table filter suitable for the XDatabaseMetaData::getTables call,
     316             :             // taking into account both the externally-provided table type filter, and any
     317             :             // table type restriction which is inherent to the container
     318           0 :             Sequence< OUString > aTableTypeFilter;
     319           0 :             OUString sInherentTableTypeRestriction( getTableTypeRestriction() );
     320           0 :             if ( !sInherentTableTypeRestriction.isEmpty() )
     321             :             {
     322           0 :                 SAL_DEBUG("OFilteredContainer::construct(). "
     323             :                           "NOT InherentTableTypeRestriction.");
     324             : 
     325           0 :                 if ( _rTableTypeFilter.getLength() != 0 )
     326             :                 {
     327           0 :                     const OUString* tableType    = _rTableTypeFilter.getConstArray();
     328           0 :                     const OUString* tableTypeEnd = tableType + _rTableTypeFilter.getLength();
     329           0 :                     for ( ; tableType != tableTypeEnd; ++tableType )
     330             :                     {
     331           0 :                         if ( *tableType == sInherentTableTypeRestriction )
     332           0 :                             break;
     333             :                     }
     334           0 :                     if ( tableType == tableTypeEnd )
     335             :                     {   // the only table type which can be part of this container is not allowed
     336             :                         // by the externally provided table type filter.
     337           0 :                         m_bConstructed = sal_True;
     338           0 :                         return;
     339             :                     }
     340             :                 }
     341           0 :                 aTableTypeFilter.realloc( 1 );
     342           0 :                 aTableTypeFilter[0] = sInherentTableTypeRestriction;
     343             :             }
     344             :             else
     345             :             {
     346           0 :                 SAL_DEBUG("OFilteredContainer::construct(). "
     347             :                           "InherentTableTypeRestriction.");
     348             : 
     349             :                 // no container-inherent restriction for the table types
     350           0 :                 if ( _rTableTypeFilter.getLength() == 0 )
     351             :                 {   // no externally-provided table type filter => use the default filter
     352           0 :                     getAllTableTypeFilter( aTableTypeFilter );
     353             :                 }
     354             :                 else
     355             :                 {
     356           0 :                     aTableTypeFilter = _rTableTypeFilter;
     357             :                 }
     358             :             }
     359             : 
     360           0 :             SAL_DEBUG("OFilteredContainer::construct(). "
     361             :                       "Getting tables ...");
     362             : 
     363           0 :             static const OUString sAll("%");
     364           0 :             Reference< XResultSet > xTables = m_xMetaData->getTables( Any(), sAll, sAll, aTableTypeFilter );
     365           0 :             Reference< XRow > xCurrentRow( xTables, UNO_QUERY_THROW );
     366             : 
     367           0 :             SAL_DEBUG("OFilteredContainer::construct(). "
     368             :                       "Tables got.");
     369             : 
     370           0 :             TableInfos aUnfilteredTables;
     371             : 
     372           0 :             OUString sCatalog, sSchema, sName, sType;
     373           0 :             while ( xTables->next() )
     374             :             {
     375           0 :                 sCatalog    = xCurrentRow->getString(1);
     376           0 :                 sSchema     = xCurrentRow->getString(2);
     377           0 :                 sName       = xCurrentRow->getString(3);
     378           0 :                 sType       = xCurrentRow->getString(4);
     379             : 
     380           0 :                 aUnfilteredTables.push_back( TableInfo( sCatalog, sSchema, sName, sType ) );
     381             :             }
     382             : 
     383             :             reFill( lcl_filter( aUnfilteredTables,
     384           0 :                 _rTableFilter, aTableTypeFilter, m_xMetaData, NULL ) );
     385             : 
     386           0 :             disposeComponent( xTables );
     387             :         }
     388           0 :         catch (const Exception&)
     389             :         {
     390             :             DBG_UNHANDLED_EXCEPTION();
     391           0 :             disposing();
     392           0 :             return;
     393             :         }
     394             : 
     395           0 :         m_bConstructed = sal_True;
     396             :     }
     397             : 
     398          33 :     void OFilteredContainer::disposing()
     399             :     {
     400          33 :         OCollection::disposing();
     401             : 
     402          33 :         if ( m_xMasterContainer.is() )
     403          29 :             removeMasterContainerListener();
     404             : 
     405          33 :         m_xMasterContainer  = NULL;
     406          33 :         m_xMetaData         = NULL;
     407          33 :         m_pWarningsContainer = NULL;
     408          33 :         m_pRefreshListener  = NULL;
     409          33 :         m_bConstructed      = sal_False;
     410          33 :     }
     411             : 
     412           0 :     void OFilteredContainer::impl_refresh() throw(RuntimeException)
     413             :     {
     414             :         SAL_INFO("dbaccess", "api OFilteredContainer::impl_refresh" );
     415           0 :         if ( m_pRefreshListener )
     416             :         {
     417           0 :             m_bConstructed = sal_False;
     418           0 :             Reference<XRefreshable> xRefresh(m_xMasterContainer,UNO_QUERY);
     419           0 :             if ( xRefresh.is() )
     420           0 :                 xRefresh->refresh();
     421           0 :             m_pRefreshListener->refresh(this);
     422             :         }
     423           0 :     }
     424             : 
     425           0 :     OUString OFilteredContainer::getNameForObject(const ObjectType& _xObject)
     426             :     {
     427             :         OSL_ENSURE( _xObject.is(), "OFilteredContainer::getNameForObject: Object is NULL!" );
     428           0 :         return ::dbtools::composeTableName( m_xMetaData, _xObject, ::dbtools::eInDataManipulation, false, false, false );
     429             :     }
     430             : 
     431             :     // multiple to obtain all tables from XDatabaseMetaData::getTables, via passing a particular
     432             :     // table type filter:
     433             :     // adhere to the standard, which requests to pass a NULL table type filter, if
     434             :     // you want to retrieve all tables
     435             :     #define FILTER_MODE_STANDARD 0
     436             :     // only pass %, which is not allowed by the standard, but understood by some drivers
     437             :     #define FILTER_MODE_WILDCARD 1
     438             :     // only pass TABLE and VIEW
     439             :     #define FILTER_MODE_FIXED    2
     440             :     // do the thing which showed to be the safest way, understood by nearly all
     441             :     // drivers, even the ones which do not understand the standard
     442             :     #define FILTER_MODE_MIX_ALL  3
     443             : 
     444           0 :     void OFilteredContainer::getAllTableTypeFilter( Sequence< OUString >& /* [out] */ _rFilter ) const
     445             :     {
     446           0 :         sal_Int32 nFilterMode = FILTER_MODE_MIX_ALL;
     447             :             // for compatibility reasons, this is the default: we used this way before we
     448             :             // introduced the TableTypeFilterMode setting
     449             : 
     450             :         // obtain the data source we belong to, and the TableTypeFilterMode setting
     451           0 :         Any aFilterModeSetting;
     452           0 :         if ( getDataSourceSetting( getDataSource( (Reference< XInterface >)m_rParent ), "TableTypeFilterMode", aFilterModeSetting ) )
     453             :         {
     454           0 :             OSL_VERIFY( aFilterModeSetting >>= nFilterMode );
     455             :         }
     456             : 
     457           0 :         const OUString sAll( "%"  );
     458           0 :         const OUString sView( "VIEW"  );
     459           0 :         const OUString sTable( "TABLE"  );
     460             : 
     461           0 :         switch ( nFilterMode )
     462             :         {
     463             :         default:
     464             :             SAL_WARN("dbaccess",  "OTableContainer::getAllTableTypeFilter: unknown TableTypeFilterMode!" );
     465             :             /* Fall through */
     466             :         case FILTER_MODE_MIX_ALL:
     467           0 :             _rFilter.realloc( 3 );
     468           0 :             _rFilter[0] = sView;
     469           0 :             _rFilter[1] = sTable;
     470           0 :             _rFilter[2] = sAll;
     471           0 :             break;
     472             :         case FILTER_MODE_FIXED:
     473           0 :             _rFilter.realloc( 2 );
     474           0 :             _rFilter[0] = sView;
     475           0 :             _rFilter[1] = sTable;
     476           0 :             break;
     477             :         case FILTER_MODE_WILDCARD:
     478           0 :             _rFilter.realloc( 1 );
     479           0 :             _rFilter[0] = sAll;
     480           0 :             break;
     481             :         case FILTER_MODE_STANDARD:
     482           0 :             _rFilter.realloc( 0 );
     483           0 :             break;
     484           0 :         }
     485           0 :     }
     486             : 
     487             : } // namespace
     488             : 
     489             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10