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

Generated by: LCOV version 1.11